aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/api.txt5
-rw-r--r--runtime/doc/deprecated.txt4
-rw-r--r--runtime/doc/lsp.txt83
-rw-r--r--runtime/doc/map.txt5
-rw-r--r--runtime/doc/options.txt16
-rw-r--r--runtime/doc/quickref.txt2
-rw-r--r--runtime/doc/treesitter.txt2
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/lua/vim/lsp.lua81
-rw-r--r--runtime/lua/vim/lsp/buf.lua31
-rw-r--r--runtime/lua/vim/lsp/handlers.lua8
-rw-r--r--runtime/lua/vim/lsp/util.lua29
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua8
-rw-r--r--runtime/optwin.vim1
-rw-r--r--src/nvim/api/autocmd.c10
-rw-r--r--src/nvim/api/keysets.lua1
-rw-r--r--src/nvim/api/ui.c6
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/auevents.lua4
-rw-r--r--src/nvim/autocmd.c17
-rw-r--r--src/nvim/autocmd.h1
-rw-r--r--src/nvim/edit.c4
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/eval/funcs.c24
-rw-r--r--src/nvim/getchar.c3
-rw-r--r--src/nvim/globals.h6
-rw-r--r--src/nvim/grid.c137
-rw-r--r--src/nvim/grid_defs.h4
-rw-r--r--src/nvim/message.c20
-rw-r--r--src/nvim/mouse.c24
-rw-r--r--src/nvim/option.c12
-rw-r--r--src/nvim/option_defs.h2
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/os/input.c9
-rw-r--r--src/nvim/popupmnu.c4
-rw-r--r--src/nvim/screen.c280
-rw-r--r--src/nvim/screen.h12
-rw-r--r--src/nvim/testdir/test_tagjump.vim9
-rw-r--r--src/nvim/ui.c4
-rw-r--r--src/nvim/ui_compositor.c62
-rw-r--r--src/nvim/window.c12
-rw-r--r--test/functional/api/autocmd_spec.lua28
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua55
-rw-r--r--test/functional/plugin/lsp_spec.lua38
-rw-r--r--test/functional/ui/float_spec.lua329
-rw-r--r--test/functional/ui/multigrid_spec.lua222
-rw-r--r--test/functional/ui/winbar_spec.lua161
47 files changed, 1361 insertions, 432 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 86ec05417c..7c669e3c9d 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -3469,6 +3469,8 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
• buf: (number) the expanded value of |<abuf>|
• file: (string) the expanded value of
|<afile>|
+ • data: (any) arbitrary data passed to
+ |nvim_exec_autocmds()|
• command (string) optional: Vim command to
execute on event. Cannot be used with
@@ -3544,6 +3546,9 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
• modeline (bool) optional: defaults to true.
Process the modeline after the autocommands
|<nomodeline>|.
+ • data (any): arbitrary data to send to the
+ autocommand callback. See
+ |nvim_create_autocmd()| for details.
See also: ~
|:doautocmd|
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
index 13644cf208..e328bd28b5 100644
--- a/runtime/doc/deprecated.txt
+++ b/runtime/doc/deprecated.txt
@@ -106,11 +106,13 @@ internally and are no longer exposed as part of the API. Instead, use
*vim.lsp.diagnostic.set_underline()*
*vim.lsp.diagnostic.set_virtual_text()*
-LSP Utility Functions ~
+LSP Functions ~
*vim.lsp.util.diagnostics_to_items()* Use |vim.diagnostic.toqflist()| instead.
*vim.lsp.util.set_qflist()* Use |setqflist()| instead.
*vim.lsp.util.set_loclist()* Use |setloclist()| instead.
+*vim.lsp.buf_get_clients()* Use |vim.lsp.get_active_clients()| with
+ {buffer = bufnr} instead.
Lua ~
*vim.register_keystroke_callback()* Use |vim.on_key()| instead.
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 569c570624..af3189a393 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -461,6 +461,39 @@ LspSignatureActiveParameter
==============================================================================
EVENTS *lsp-events*
+ *LspAttach*
+After an LSP client attaches to a buffer. The |autocmd-pattern| is the
+name of the buffer. When used from Lua, the client ID is passed to the
+callback in the "data" table. Example: >
+
+ vim.api.nvim_create_autocmd("LspAttach", {
+ callback = function(args)
+ local bufnr = args.buf
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ if client.server_capabilities.completionProvider then
+ vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc"
+ end
+ if client.server_capabilities.definitionProvider then
+ vim.bo[bufnr].tagfunc = "v:lua.vim.lsp.tagfunc"
+ end
+ end,
+ })
+<
+ *LspDetach*
+Just before an LSP client detaches from a buffer. The |autocmd-pattern| is the
+name of the buffer. When used from Lua, the client ID is passed to the
+callback in the "data" table. Example: >
+
+ vim.api.nvim_create_autocmd("LspDetach", {
+ callback = function(args)
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ -- Do something with the client
+ vim.cmd("setlocal tagfunc< omnifunc<")
+ end,
+ })
+<
+In addition, the following |User| |autocommands| are provided:
+
LspProgressUpdate *LspProgressUpdate*
Upon receipt of a progress notification from the server. See
|vim.lsp.util.get_progress_messages()|.
@@ -498,14 +531,6 @@ buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()*
{bufnr} (number) Buffer handle, or 0 for current
{client_id} (number) Client id
-buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()*
- Gets a map of client_id:client pairs for the given buffer,
- where each value is a |vim.lsp.client| object.
-
- Parameters: ~
- {bufnr} (optional, number): Buffer handle, or 0 for
- current
-
buf_is_attached({bufnr}, {client_id}) *vim.lsp.buf_is_attached()*
Checks if a buffer is attached for a particular client.
@@ -696,11 +721,22 @@ formatexpr({opts}) *vim.lsp.formatexpr()*
• timeout_ms (default 500ms). The timeout period
for the formatting request.
-get_active_clients() *vim.lsp.get_active_clients()*
- Gets all active clients.
+get_active_clients({filter}) *vim.lsp.get_active_clients()*
+ Get active clients.
+
+ Parameters: ~
+ {filter} (table|nil) A table with key-value pairs used to
+ filter the returned clients. The available keys
+ are:
+ • id (number): Only return clients with the
+ given id
+ • bufnr (number): Only return clients attached
+ to this buffer
+ • name (string): Only return clients with the
+ given name
Return: ~
- Table of |vim.lsp.client| objects
+ (table) List of |vim.lsp.client| objects
*vim.lsp.get_buffers_by_client_id()*
get_buffers_by_client_id({client_id})
@@ -1015,15 +1051,25 @@ completion({context}) *vim.lsp.buf.completion()*
See also: ~
|vim.lsp.protocol.constants.CompletionTriggerKind|
-declaration() *vim.lsp.buf.declaration()*
+declaration({options}) *vim.lsp.buf.declaration()*
Jumps to the declaration of the symbol under the cursor.
Note:
Many servers do not implement this method. Generally, see
|vim.lsp.buf.definition()| instead.
-definition() *vim.lsp.buf.definition()*
+ Parameters: ~
+ {options} (table|nil) additional options
+ • reuse_win: (boolean) Jump to existing window
+ if buffer is already open.
+
+definition({options}) *vim.lsp.buf.definition()*
Jumps to the definition of the symbol under the cursor.
+ Parameters: ~
+ {options} (table|nil) additional options
+ • reuse_win: (boolean) Jump to existing window
+ if buffer is already open.
+
document_highlight() *vim.lsp.buf.document_highlight()*
Send request to the server to resolve document highlights for
the current text document position. This request can be
@@ -1250,10 +1296,15 @@ signature_help() *vim.lsp.buf.signature_help()*
Displays signature information about the symbol under the
cursor in a floating window.
-type_definition() *vim.lsp.buf.type_definition()*
+type_definition({options}) *vim.lsp.buf.type_definition()*
Jumps to the definition of the type of the symbol under the
cursor.
+ Parameters: ~
+ {options} (table|nil) additional options
+ • reuse_win: (boolean) Jump to existing window
+ if buffer is already open.
+
workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()*
Lists all symbols in the current workspace in the quickfix
window.
@@ -1539,12 +1590,14 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()*
|shiftwidth|
*vim.lsp.util.jump_to_location()*
-jump_to_location({location}, {offset_encoding})
+jump_to_location({location}, {offset_encoding}, {reuse_win})
Jumps to a location.
Parameters: ~
{location} (table) (`Location`|`LocationLink`)
{offset_encoding} (string) utf-8|utf-16|utf-32 (required)
+ {reuse_win} (boolean) Jump to existing window if
+ buffer is already opened.
Return: ~
`true` if the jump succeeded
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 056e6c3b56..98da68b76a 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -796,9 +796,8 @@ command. For example: >
:noremap j k
This will exchange the cursor up and down commands.
-With the normal :map command, when the 'remap' option is on, mapping takes
-place until the text is found not to be a part of a {lhs}. For example, if
-you use: >
+With the normal :map command mapping takes place until the text is found not
+to be a part of a {lhs}. For example, if you use: >
:map x y
:map y x
Vim will replace x with y, and then y with x, etc. When this has happened
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 4022bc4334..b49512e1e6 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4800,15 +4800,6 @@ A jump table for the options with a short description can be found at |Q_op|.
'number', see |number_relativenumber| for all combinations of the two
options.
- *'remap'* *'noremap'*
-'remap' boolean (default on)
- global
- Allows for mappings to work recursively. If you do not want this for
- a single entry, use the :noremap[!] command.
- NOTE: To avoid portability problems with Vim scripts, always keep
- this option at the default "on". Only switch it off when working with
- old Vi scripts.
-
*'report'*
'report' number (default 2)
global
@@ -6480,13 +6471,6 @@ A jump table for the options with a short description can be found at |Q_op|.
C1 Control characters 0x80...0x9F
- *'terse'* *'noterse'*
-'terse' boolean (default off)
- global
- When set: Add 's' flag to 'shortmess' option (this makes the message
- for a search that hits the start or end of the file not being
- displayed). When reset: Remove 's' flag from 'shortmess' option.
-
*'textwidth'* *'tw'*
'textwidth' 'tw' number (default 0)
local to buffer
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index 961d734bfe..ff7e2ab400 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -824,7 +824,6 @@ Short explanation of each option: *option-list*
'redrawtime' 'rdt' timeout for 'hlsearch' and |:match| highlighting
'regexpengine' 're' default regexp engine to use
'relativenumber' 'rnu' show relative line number in front of each line
-'remap' allow mappings to work recursively
'report' threshold for reporting nr. of lines changed
'revins' 'ri' inserting characters will work backwards
'rightleft' 'rl' window is right-to-left oriented
@@ -896,7 +895,6 @@ Short explanation of each option: *option-list*
'tagstack' 'tgst' push tags onto the tag stack
'term' name of the terminal
'termbidi' 'tbidi' terminal takes care of bi-directionality
-'terse' shorten some messages
'textwidth' 'tw' maximum width of text that is being inserted
'thesaurus' 'tsr' list of thesaurus files for keyword completion
'thesaurusfunc' 'tsrfu' function to be used for thesaurus completion
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index bc264bd971..339ae0c2ed 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -616,8 +616,6 @@ LanguageTree:children({self}) *LanguageTree:children()*
LanguageTree:contains({self}, {range}) *LanguageTree:contains()*
Determines whether {range} is contained in this language tree
- This goes down the tree to recursively check children.
-
Parameters: ~
{range} A range, that is a `{ start_line, start_col,
end_line, end_col }` table.
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index fc98331697..c926337b47 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -548,11 +548,13 @@ Options:
'maxmemtot' Nvim delegates memory-management to the OS.
'maxcombine' (6 is always used)
*'prompt'* *'noprompt'*
+ *'remap'* *'noremap'*
*'restorescreen'* *'rs'* *'norestorescreen'* *'nors'*
'shelltype'
*'shortname'* *'sn'* *'noshortname'* *'nosn'*
*'swapsync'* *'sws'*
*'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows)
+ *'terse'* *'noterse'* (Add "s" to 'shortmess' instead)
'textauto'
'textmode'
*'toolbar'* *'tb'*
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index e99a7c282c..07987ee003 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -1,5 +1,3 @@
-local if_nil = vim.F.if_nil
-
local default_handlers = require('vim.lsp.handlers')
local log = require('vim.lsp.log')
local lsp_rpc = require('vim.lsp.rpc')
@@ -8,11 +6,16 @@ local util = require('vim.lsp.util')
local sync = require('vim.lsp.sync')
local vim = vim
-local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option =
- vim.api.nvim_err_writeln, vim.api.nvim_buf_get_lines, vim.api.nvim_command, vim.api.nvim_buf_get_option
+local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option, nvim_exec_autocmds =
+ vim.api.nvim_err_writeln,
+ vim.api.nvim_buf_get_lines,
+ vim.api.nvim_command,
+ vim.api.nvim_buf_get_option,
+ vim.api.nvim_exec_autocmds
local uv = vim.loop
local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend
local validate = vim.validate
+local if_nil = vim.F.if_nil
local lsp = {
protocol = protocol,
@@ -867,15 +870,27 @@ function lsp.start_client(config)
pcall(config.on_exit, code, signal, client_id)
end
+ for bufnr, client_ids in pairs(all_buffer_active_clients) do
+ if client_ids[client_id] then
+ vim.schedule(function()
+ nvim_exec_autocmds('LspDetach', {
+ buffer = bufnr,
+ modeline = false,
+ data = { client_id = client_id },
+ })
+
+ local namespace = vim.lsp.diagnostic.get_namespace(client_id)
+ vim.diagnostic.reset(namespace, bufnr)
+ end)
+
+ client_ids[client_id] = nil
+ end
+ end
+
active_clients[client_id] = nil
uninitialized_clients[client_id] = nil
- lsp.diagnostic.reset(client_id, all_buffer_active_clients)
changetracking.reset(client_id)
- for _, client_ids in pairs(all_buffer_active_clients) do
- client_ids[client_id] = nil
- end
-
if code ~= 0 or (signal ~= 0 and signal ~= 15) then
local msg = string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal)
vim.schedule(function()
@@ -1213,6 +1228,13 @@ function lsp.start_client(config)
---@param bufnr (number) Buffer number
function client._on_attach(bufnr)
text_document_did_open_handler(bufnr, client)
+
+ nvim_exec_autocmds('LspAttach', {
+ buffer = bufnr,
+ modeline = false,
+ data = { client_id = client.id },
+ })
+
if config.on_attach then
-- TODO(ashkan) handle errors.
pcall(config.on_attach, client, bufnr)
@@ -1359,6 +1381,12 @@ function lsp.buf_detach_client(bufnr, client_id)
return
end
+ nvim_exec_autocmds('LspDetach', {
+ buffer = bufnr,
+ modeline = false,
+ data = { client_id = client_id },
+ })
+
changetracking.reset_buf(client, bufnr)
if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
@@ -1435,11 +1463,29 @@ function lsp.stop_client(client_id, force)
end
end
---- Gets all active clients.
+--- Get active clients.
---
----@returns Table of |vim.lsp.client| objects
-function lsp.get_active_clients()
- return vim.tbl_values(active_clients)
+---@param filter (table|nil) A table with key-value pairs used to filter the
+--- returned clients. The available keys are:
+--- - id (number): Only return clients with the given id
+--- - bufnr (number): Only return clients attached to this buffer
+--- - name (string): Only return clients with the given name
+---@returns (table) List of |vim.lsp.client| objects
+function lsp.get_active_clients(filter)
+ validate({ filter = { filter, 't', true } })
+
+ filter = filter or {}
+
+ local clients = {}
+
+ local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {}) or active_clients
+ for client_id in pairs(t) do
+ local client = active_clients[client_id]
+ if (filter.id == nil or client.id == filter.id) and (filter.name == nil or client.name == filter.name) then
+ clients[#clients + 1] = client
+ end
+ end
+ return clients
end
function lsp._vim_exit_handler()
@@ -1814,12 +1860,13 @@ end
--- is a |vim.lsp.client| object.
---
---@param bufnr (optional, number): Buffer handle, or 0 for current
+---@returns (table) Table of (client_id, client) pairs
+---@deprecated Use |vim.lsp.get_active_clients()| instead.
function lsp.buf_get_clients(bufnr)
- bufnr = resolve_bufnr(bufnr)
local result = {}
- for_each_buffer_client(bufnr, function(client, client_id)
- result[client_id] = client
- end)
+ for _, client in ipairs(lsp.get_active_clients({ bufnr = resolve_bufnr(bufnr) })) do
+ result[client.id] = client
+ end
return result
end
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index b0bf2c6e5b..80350bcb71 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -63,26 +63,45 @@ function M.hover()
request('textDocument/hover', params)
end
+---@private
+local function request_with_options(name, params, options)
+ local req_handler
+ if options then
+ req_handler = function(err, result, ctx, config)
+ local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local handler = client.handlers[name] or vim.lsp.handlers[name]
+ handler(err, result, ctx, vim.tbl_extend('force', config or {}, options))
+ end
+ end
+ request(name, params, req_handler)
+end
+
--- Jumps to the declaration of the symbol under the cursor.
---@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead.
---
-function M.declaration()
+---@param options table|nil additional options
+--- - reuse_win: (boolean) Jump to existing window if buffer is already open.
+function M.declaration(options)
local params = util.make_position_params()
- request('textDocument/declaration', params)
+ request_with_options('textDocument/declaration', params, options)
end
--- Jumps to the definition of the symbol under the cursor.
---
-function M.definition()
+---@param options table|nil additional options
+--- - reuse_win: (boolean) Jump to existing window if buffer is already open.
+function M.definition(options)
local params = util.make_position_params()
- request('textDocument/definition', params)
+ request_with_options('textDocument/definition', params, options)
end
--- Jumps to the definition of the type of the symbol under the cursor.
---
-function M.type_definition()
+---@param options table|nil additional options
+--- - reuse_win: (boolean) Jump to existing window if buffer is already open.
+function M.type_definition(options)
local params = util.make_position_params()
- request('textDocument/typeDefinition', params)
+ request_with_options('textDocument/typeDefinition', params, options)
end
--- Lists all the implementations for the symbol under the cursor in the
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index b3a253c118..61cc89dcac 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -327,18 +327,20 @@ M['textDocument/hover'] = M.hover
---@param result (table) result of LSP method; a location or a list of locations.
---@param ctx (table) table containing the context of the request, including the method
---(`textDocument/definition` can return `Location` or `Location[]`
-local function location_handler(_, result, ctx, _)
+local function location_handler(_, result, ctx, config)
if result == nil or vim.tbl_isempty(result) then
local _ = log.info() and log.info(ctx.method, 'No location found')
return nil
end
local client = vim.lsp.get_client_by_id(ctx.client_id)
+ config = config or {}
+
-- textDocument/definition can return Location or Location[]
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
if vim.tbl_islist(result) then
- util.jump_to_location(result[1], client.offset_encoding)
+ util.jump_to_location(result[1], client.offset_encoding, config.reuse_win)
if #result > 1 then
vim.fn.setqflist({}, ' ', {
@@ -348,7 +350,7 @@ local function location_handler(_, result, ctx, _)
api.nvim_command('botright copen')
end
else
- util.jump_to_location(result, client.offset_encoding)
+ util.jump_to_location(result, client.offset_encoding, config.reuse_win)
end
end
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index e8a8e06f46..0b0d48d15e 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -684,6 +684,16 @@ function M.text_document_completion_list_to_complete_items(result, prefix)
return matches
end
+---@private
+--- Like vim.fn.bufwinid except it works across tabpages.
+local function bufwinid(bufnr)
+ for _, win in ipairs(api.nvim_list_wins()) do
+ if api.nvim_win_get_buf(win) == bufnr then
+ return win
+ end
+ end
+end
+
--- Rename old_fname to new_fname
---
---@param opts (table)
@@ -708,10 +718,9 @@ function M.rename(old_fname, new_fname, opts)
assert(ok, err)
local newbuf = vim.fn.bufadd(new_fname)
- for _, win in pairs(api.nvim_list_wins()) do
- if api.nvim_win_get_buf(win) == oldbuf then
- api.nvim_win_set_buf(win, newbuf)
- end
+ local win = bufwinid(oldbuf)
+ if win then
+ api.nvim_win_set_buf(win, newbuf)
end
api.nvim_buf_delete(oldbuf, { force = true })
end
@@ -1004,8 +1013,9 @@ end
---
---@param location table (`Location`|`LocationLink`)
---@param offset_encoding string utf-8|utf-16|utf-32 (required)
+---@param reuse_win boolean Jump to existing window if buffer is already opened.
---@returns `true` if the jump succeeded
-function M.jump_to_location(location, offset_encoding)
+function M.jump_to_location(location, offset_encoding, reuse_win)
-- location may be Location or LocationLink
local uri = location.uri or location.targetUri
if uri == nil then
@@ -1024,8 +1034,13 @@ function M.jump_to_location(location, offset_encoding)
vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't')
--- Jump to new location (adjusting for UTF-16 encoding of characters)
- api.nvim_set_current_buf(bufnr)
- api.nvim_buf_set_option(bufnr, 'buflisted', true)
+ local win = reuse_win and bufwinid(bufnr)
+ if win then
+ api.nvim_set_current_win(win)
+ else
+ api.nvim_set_current_buf(bufnr)
+ api.nvim_buf_set_option(bufnr, 'buflisted', true)
+ end
local range = location.range or location.targetSelectionRange
local row = range.start.line
local col = get_line_byte_from_position(bufnr, range.start, offset_encoding)
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 2157112d2f..57d8c5fd21 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -519,17 +519,11 @@ local function tree_contains(tree, range)
local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2])
local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4])
- if start_fits and end_fits then
- return true
- end
-
- return false
+ return start_fits and end_fits
end
--- Determines whether {range} is contained in this language tree
---
---- This goes down the tree to recursively check children.
----
---@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table.
function LanguageTree:contains(range)
for _, tree in pairs(self._trees) do
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index a13e945098..493f7b57d0 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -956,7 +956,6 @@ call <SID>Header("mapping")
call append("$", "maxmapdepth\tmaximum depth of mapping")
call append("$", " \tset mmd=" . &mmd)
call append("$", "remap\trecognize mappings in mapped keys")
-call <SID>BinOptionG("remap", &remap)
call append("$", "timeout\tallow timing out halfway into a mapping")
call <SID>BinOptionG("to", &to)
call append("$", "ttimeout\tallow timing out halfway into a key code")
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 76e531e7aa..30a5d60c39 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -405,6 +405,7 @@ cleanup:
/// - match: (string) the expanded value of |<amatch>|
/// - buf: (number) the expanded value of |<abuf>|
/// - file: (string) the expanded value of |<afile>|
+/// - data: (any) arbitrary data passed to |nvim_exec_autocmds()|
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
@@ -749,6 +750,8 @@ void nvim_del_augroup_by_name(String name, Error *err)
/// {pattern}.
/// - modeline (bool) optional: defaults to true. Process the
/// modeline after the autocommands |<nomodeline>|.
+/// - data (any): arbitrary data to send to the autocommand callback. See
+/// |nvim_create_autocmd()| for details.
/// @see |:doautocmd|
void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
FUNC_API_SINCE(9)
@@ -760,6 +763,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
bool set_buf = false;
char *pattern = NULL;
+ Object *data = NULL;
bool set_pattern = false;
Array event_array = ARRAY_DICT_INIT;
@@ -818,6 +822,10 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
set_pattern = true;
}
+ if (opts->data.type != kObjectTypeNil) {
+ data = &opts->data;
+ }
+
modeline = api_object_to_bool(opts->modeline, "modeline", true, err);
if (set_pattern && set_buf) {
@@ -829,7 +837,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
FOREACH_ITEM(event_array, event_str, {
GET_ONE_EVENT(event_nr, event_str, cleanup)
- did_aucmd |= apply_autocmds_group(event_nr, pattern, NULL, true, au_group, buf, NULL);
+ did_aucmd |= apply_autocmds_group(event_nr, pattern, NULL, true, au_group, buf, NULL, data);
})
if (did_aucmd && modeline) {
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 27228204e0..6924e2ef8f 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -146,6 +146,7 @@ return {
"group";
"modeline";
"pattern";
+ "data";
};
get_autocmds = {
"event";
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index b4d20ed975..52f76f4650 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -349,7 +349,11 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, I
return;
}
- ui_grid_resize((handle_T)grid, (int)width, (int)height, err);
+ if (grid == DEFAULT_GRID_HANDLE) {
+ nvim_ui_try_resize(channel_id, width, height, err);
+ } else {
+ ui_grid_resize((handle_T)grid, (int)width, (int)height, err);
+ }
}
/// Tells Nvim the number of elements displaying in the popumenu, to decide
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 3c378e73e1..15992a98be 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -2140,8 +2140,8 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err)
}
}
- if (row < 0 || row >= g->Rows
- || col < 0 || col >= g->Columns) {
+ if (row < 0 || row >= g->rows
+ || col < 0 || col >= g->cols) {
return ret;
}
size_t off = g->line_offset[(size_t)row] + (size_t)col;
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 9e3eb06752..93a870fe04 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -70,6 +70,8 @@ return {
'InsertEnter', -- when entering Insert mode
'InsertLeave', -- just after leaving Insert mode
'InsertLeavePre', -- just before leaving Insert mode
+ 'LspAttach', -- after an LSP client attaches to a buffer
+ 'LspDetach', -- after an LSP client detaches from a buffer
'MenuPopup', -- just before popup menu is displayed
'ModeChanged', -- after changing the mode
'OptionSet', -- after setting any option
@@ -133,6 +135,8 @@ return {
nvim_specific = {
BufModifiedSet=true,
DiagnosticChanged=true,
+ LspAttach=true,
+ LspDetach=true,
RecordingEnter=true,
RecordingLeave=true,
Signal=true,
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 6c7950fdd1..b87c7886e3 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1220,7 +1220,7 @@ int do_doautocmd(char *arg_start, bool do_msg, bool *did_something)
// Loop over the events.
while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) {
if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true, group,
- curbuf, NULL)) {
+ curbuf, NULL, NULL)) {
nothing_done = false;
}
}
@@ -1505,7 +1505,7 @@ win_found:
/// @return true if some commands were executed.
bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_T *buf)
{
- return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL);
+ return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL, NULL);
}
/// Like apply_autocmds(), but with extra "eap" argument. This takes care of
@@ -1522,7 +1522,7 @@ bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_
bool apply_autocmds_exarg(event_T event, char *fname, char *fname_io, bool force, buf_T *buf,
exarg_T *eap)
{
- return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap);
+ return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap, NULL);
}
/// Like apply_autocmds(), but handles the caller's retval. If the script
@@ -1546,7 +1546,7 @@ bool apply_autocmds_retval(event_T event, char *fname, char *fname_io, bool forc
}
bool did_cmd = apply_autocmds_group(event, fname, fname_io, force,
- AUGROUP_ALL, buf, NULL);
+ AUGROUP_ALL, buf, NULL, NULL);
if (did_cmd && aborting()) {
*retval = FAIL;
}
@@ -1595,7 +1595,7 @@ bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
///
/// @return true if some commands were executed.
bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force, int group,
- buf_T *buf, exarg_T *eap)
+ buf_T *buf, exarg_T *eap, Object *data)
{
char *sfname = NULL; // short file name
bool retval = false;
@@ -1811,6 +1811,9 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
patcmd.next = active_apc_list;
active_apc_list = &patcmd;
+ // Attach data to command
+ patcmd.data = data;
+
// set v:cmdarg (only when there is a matching pattern)
save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
if (eap != NULL) {
@@ -2026,6 +2029,10 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
PUT(data, "file", CSTR_TO_OBJ((char *)autocmd_fname));
PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr));
+ if (apc->data) {
+ PUT(data, "data", copy_object(*apc->data));
+ }
+
int group = apc->curpat->group;
switch (group) {
case AUGROUP_ERROR:
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index d3503672fd..47f583ae13 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -57,6 +57,7 @@ typedef struct AutoPatCmd {
char *tail; // tail of fname
event_T event; // current event
int arg_bufnr; // initially equal to <abuf>, set to zero when buf is deleted
+ Object *data; // arbitrary data
struct AutoPatCmd *next; // chain of active apc-s for auto-invalidation
} AutoPatCmd;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index aa77c03b48..d7e82729a9 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1632,7 +1632,7 @@ void edit_putchar(int c, bool highlight)
pc_col = 0;
pc_status = PC_STATUS_UNSET;
if (curwin->w_p_rl) {
- pc_col += curwin->w_grid.Columns - 1 - curwin->w_wcol;
+ pc_col += curwin->w_grid.cols - 1 - curwin->w_wcol;
const int fix_col = grid_fix_col(&curwin->w_grid, pc_col, pc_row);
if (fix_col != pc_col) {
@@ -1759,7 +1759,7 @@ void display_dollar(colnr_T col)
char_u *p = get_cursor_line_ptr();
curwin->w_cursor.col -= utf_head_off(p, p + col);
curs_columns(curwin, false); // Recompute w_wrow and w_wcol
- if (curwin->w_wcol < curwin->w_grid.Columns) {
+ if (curwin->w_wcol < curwin->w_grid.cols) {
edit_putchar('$', false);
dollar_vcol = curwin->w_virtcol;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index f9c6b6fbb2..641dcae55e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6865,8 +6865,8 @@ void screenchar_adjust_grid(ScreenGrid **grid, int *row, int *col)
// have its own buffer, this should just read from it instead.
msg_scroll_flush();
if (msg_grid.chars && msg_grid.comp_index > 0 && *row >= msg_grid.comp_row
- && *row < (msg_grid.Rows + msg_grid.comp_row)
- && *col < msg_grid.Columns) {
+ && *row < (msg_grid.rows + msg_grid.comp_row)
+ && *col < msg_grid.cols) {
*grid = &msg_grid;
*row -= msg_grid.comp_row;
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index ad133b5b5f..62fe2033af 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -8047,8 +8047,8 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
- if (row < 0 || row >= default_grid.Rows
- || col < 0 || col >= default_grid.Columns) {
+ if (row < 0 || row >= default_grid.rows
+ || col < 0 || col >= default_grid.cols) {
c = -1;
} else {
ScreenGrid *grid = &default_grid;
@@ -8065,8 +8065,8 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int row = tv_get_number_chk(&argvars[0], NULL) - 1;
int col = tv_get_number_chk(&argvars[1], NULL) - 1;
- if (row < 0 || row >= default_grid.Rows
- || col < 0 || col >= default_grid.Columns) {
+ if (row < 0 || row >= default_grid.rows
+ || col < 0 || col >= default_grid.cols) {
c = -1;
} else {
ScreenGrid *grid = &default_grid;
@@ -8081,8 +8081,8 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int row = tv_get_number_chk(&argvars[0], NULL) - 1;
int col = tv_get_number_chk(&argvars[1], NULL) - 1;
- if (row < 0 || row >= default_grid.Rows
- || col < 0 || col >= default_grid.Columns) {
+ if (row < 0 || row >= default_grid.rows
+ || col < 0 || col >= default_grid.cols) {
tv_list_alloc_ret(rettv, 0);
return;
}
@@ -8148,8 +8148,8 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
int row = tv_get_number_chk(&argvars[0], NULL) - 1;
int col = tv_get_number_chk(&argvars[1], NULL) - 1;
- if (row < 0 || row >= default_grid.Rows
- || col < 0 || col >= default_grid.Columns) {
+ if (row < 0 || row >= default_grid.rows
+ || col < 0 || col >= default_grid.cols) {
return;
}
ScreenGrid *grid = &default_grid;
@@ -10790,10 +10790,16 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// "/home/foo/…" => "~/…"
size_t len = home_replace(NULL, NameBuff, IObuff, sizeof(IObuff), true);
// Trim slash.
- if (IObuff[len - 1] == '\\' || IObuff[len - 1] == '/') {
+ if (len != 1 && (IObuff[len - 1] == '\\' || IObuff[len - 1] == '/')) {
IObuff[len - 1] = '\0';
}
+ if (len == 1 && IObuff[0] == '/') {
+ // Avoid ambiguity in the URI when CWD is root directory.
+ IObuff[1] = '.';
+ IObuff[2] = '\0';
+ }
+
// Terminal URI: "term://$CWD//$PID:$CMD"
snprintf((char *)NameBuff, sizeof(NameBuff), "term://%s//%d:%s",
(char *)IObuff, pid, cmd);
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 2cc068b30d..8881263d1c 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1881,8 +1881,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
if (no_mapping == 0 && maphash_valid
&& (no_zero_mapping == 0 || tb_c1 != '0')
&& (typebuf.tb_maplen == 0 || is_plug_map
- || (p_remap
- && !(typebuf.tb_noremap[typebuf.tb_off] & (RM_NONE|RM_ABBR))))
+ || (!(typebuf.tb_noremap[typebuf.tb_off] & (RM_NONE|RM_ABBR))))
&& !(p_paste && (State & (MODE_INSERT | MODE_CMDLINE)))
&& !(State == MODE_HITRETURN && (tb_c1 == CAR || tb_c1 == ' '))
&& State != MODE_ASKMORE
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 3231ac011a..1819af7ee4 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -84,7 +84,7 @@ EXTERN struct nvim_stats_s {
// 0 not starting anymore
// Number of Rows and Columns in the screen.
-// Note: Use default_grid.Rows and default_grid.Columns to access items in
+// Note: Use default_grid.rows and default_grid.cols to access items in
// default_grid.chars[]. They may have different values when the screen
// wasn't (re)allocated yet after setting Rows or Columns (e.g., when starting
// up).
@@ -421,10 +421,6 @@ EXTERN vimmenu_T *root_menu INIT(= NULL);
// overruling of menus that the user already defined.
EXTERN int sys_menu INIT(= false);
-// While redrawing the screen this flag is set. It means the screen size
-// ('lines' and 'rows') must not be changed.
-EXTERN int updating_screen INIT(= 0);
-
// All windows are linked in a list. firstwin points to the first entry,
// lastwin to the last entry (can be the same as firstwin) and curwin to the
// currently active window.
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 13429994de..fa5c193fe0 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -6,6 +6,7 @@
#include "nvim/highlight.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
+#include "nvim/screen.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "grid.c.generated.h"
@@ -63,7 +64,7 @@ void grid_clear_line(ScreenGrid *grid, size_t off, int width, bool valid)
void grid_invalidate(ScreenGrid *grid)
{
- (void)memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)grid->Rows * (size_t)grid->Columns);
+ (void)memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)grid->rows * (size_t)grid->cols);
}
bool grid_invalid_row(ScreenGrid *grid, int row)
@@ -92,7 +93,7 @@ bool grid_lefthalve(ScreenGrid *grid, int row, int col)
grid_adjust(&grid, &row, &col);
return grid_off2cells(grid, grid->line_offset[row] + (size_t)col,
- grid->line_offset[row] + (size_t)grid->Columns) > 1;
+ grid->line_offset[row] + (size_t)grid->cols) > 1;
}
/// Correct a position on the screen, if it's the right half of a double-wide
@@ -128,7 +129,7 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes, int *attrp
grid_adjust(&grid, &row, &col);
// safety check
- if (grid->chars != NULL && row < grid->Rows && col < grid->Columns) {
+ if (grid->chars != NULL && row < grid->rows && col < grid->cols) {
off = grid->line_offset[row] + (size_t)col;
*attrp = grid->attrs[off];
schar_copy(bytes, grid->chars[off]);
@@ -202,8 +203,8 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col
// Safety check. The check for negative row and column is to fix issue
// vim/vim#4102. TODO(neovim): find out why row/col could be negative.
if (grid->chars == NULL
- || row >= grid->Rows || row < 0
- || col >= grid->Columns || col < 0) {
+ || row >= grid->rows || row < 0
+ || col >= grid->cols || col < 0) {
return;
}
@@ -225,8 +226,8 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col
put_dirty_last = MAX(put_dirty_last, 1);
}
- max_off = grid->line_offset[row] + (size_t)grid->Columns;
- while (col < grid->Columns
+ max_off = grid->line_offset[row] + (size_t)grid->cols;
+ while (col < grid->cols
&& (len < 0 || (int)(ptr - text) < len)
&& *ptr != NUL) {
c = *ptr;
@@ -259,7 +260,7 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col
} else {
prev_c = u8c;
}
- if (col + mbyte_cells > grid->Columns) {
+ if (col + mbyte_cells > grid->cols) {
// Only 1 cell left, but character requires 2 cells:
// display a '>' in the last column to avoid wrapping. */
c = '>';
@@ -338,7 +339,7 @@ void grid_puts_line_flush(bool set_cursor)
if (put_dirty_first < put_dirty_last) {
if (set_cursor) {
ui_grid_cursor_goto(put_dirty_grid->handle, put_dirty_row,
- MIN(put_dirty_last, put_dirty_grid->Columns - 1));
+ MIN(put_dirty_last, put_dirty_grid->cols - 1));
}
if (!put_dirty_grid->throttled) {
ui_line(put_dirty_grid, put_dirty_row, put_dirty_first, put_dirty_last,
@@ -371,11 +372,11 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
end_col += col_off;
// safety check
- if (end_row > grid->Rows) {
- end_row = grid->Rows;
+ if (end_row > grid->rows) {
+ end_row = grid->rows;
}
- if (end_col > grid->Columns) {
- end_col = grid->Columns;
+ if (end_col > grid->cols) {
+ end_col = grid->cols;
}
// nothing to do
@@ -391,7 +392,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
if (start_col > 0 && grid_fix_col(grid, start_col, row) != start_col) {
grid_puts_len(grid, (char_u *)" ", 1, row, start_col - 1, 0);
}
- if (end_col < grid->Columns
+ if (end_col < grid->cols
&& grid_fix_col(grid, end_col, row) != end_col) {
grid_puts_len(grid, (char_u *)" ", 1, row, end_col, 0);
}
@@ -443,7 +444,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
}
}
- if (end_col == grid->Columns) {
+ if (end_col == grid->cols) {
grid->line_wraps[row] = false;
}
}
@@ -491,17 +492,17 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
// TODO(bfredl): check all callsites and eliminate
// Check for illegal row and col, just in case
- if (row >= grid->Rows) {
- row = grid->Rows - 1;
+ if (row >= grid->rows) {
+ row = grid->rows - 1;
}
- if (endcol > grid->Columns) {
- endcol = grid->Columns;
+ if (endcol > grid->cols) {
+ endcol = grid->cols;
}
grid_adjust(&grid, &row, &coloff);
// Safety check. Avoids clang warnings down the call stack.
- if (grid->chars == NULL || row >= grid->Rows || coloff >= grid->Columns) {
+ if (grid->chars == NULL || row >= grid->rows || coloff >= grid->cols) {
DLOG("invalid state, skipped");
return;
}
@@ -509,7 +510,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
size_t off_from = 0;
size_t off_to = grid->line_offset[row] + (size_t)coloff;
max_off_from = linebuf_size;
- max_off_to = grid->line_offset[row] + (size_t)grid->Columns;
+ max_off_to = grid->line_offset[row] + (size_t)grid->cols;
if (rlflag) {
// Clear rest first, because it's left of the text.
@@ -617,7 +618,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
}
}
- if (clear_width > 0 || wp->w_width != grid->Columns) {
+ if (clear_width > 0 || wp->w_width != grid->cols) {
// If we cleared after the end of the line, it did not wrap.
// For vsplit, line wrapping is not possible.
grid->line_wraps[row] = false;
@@ -646,11 +647,11 @@ void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy, bool valid)
new.line_offset = xmalloc((size_t)rows * sizeof(*new.line_offset));
new.line_wraps = xmalloc((size_t)rows * sizeof(*new.line_wraps));
- new.Rows = rows;
- new.Columns = columns;
+ new.rows = rows;
+ new.cols = columns;
- for (new_row = 0; new_row < new.Rows; new_row++) {
- new.line_offset[new_row] = (size_t)new_row * (size_t)new.Columns;
+ for (new_row = 0; new_row < new.rows; new_row++) {
+ new.line_offset[new_row] = (size_t)new_row * (size_t)new.cols;
new.line_wraps[new_row] = false;
grid_clear_line(&new, new.line_offset[new_row], columns, valid);
@@ -660,8 +661,8 @@ void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy, bool valid)
// possible from the old screen to the new one and clear the rest
// (used when resizing the window at the "--more--" prompt or when
// executing an external command, for the GUI).
- if (new_row < grid->Rows && grid->chars != NULL) {
- int len = MIN(grid->Columns, new.Columns);
+ if (new_row < grid->rows && grid->chars != NULL) {
+ int len = MIN(grid->cols, new.cols);
memmove(new.chars + new.line_offset[new_row],
grid->chars + grid->line_offset[new_row],
(size_t)len * sizeof(schar_T));
@@ -705,3 +706,83 @@ void grid_free_all_mem(void)
xfree(linebuf_char);
xfree(linebuf_attr);
}
+
+/// (Re)allocates a window grid if size changed while in ext_multigrid mode.
+/// Updates size, offsets and handle for the grid regardless.
+///
+/// If "doclear" is true, don't try to copy from the old grid rather clear the
+/// resized grid.
+void win_grid_alloc(win_T *wp)
+{
+ ScreenGrid *grid = &wp->w_grid;
+ ScreenGrid *grid_allocated = &wp->w_grid_alloc;
+
+ int rows = wp->w_height_inner;
+ int cols = wp->w_width_inner;
+ int total_rows = wp->w_height_outer;
+ int total_cols = wp->w_width_outer;
+
+ bool want_allocation = ui_has(kUIMultigrid) || wp->w_floating;
+ bool has_allocation = (grid_allocated->chars != NULL);
+
+ if (grid->rows != rows) {
+ wp->w_lines_valid = 0;
+ xfree(wp->w_lines);
+ wp->w_lines = xcalloc((size_t)rows + 1, sizeof(wline_T));
+ }
+
+ int was_resized = false;
+ if (want_allocation && (!has_allocation
+ || grid_allocated->rows != total_rows
+ || grid_allocated->cols != total_cols)) {
+ grid_alloc(grid_allocated, total_rows, total_cols,
+ wp->w_grid_alloc.valid, false);
+ grid_allocated->valid = true;
+ if (wp->w_floating && wp->w_float_config.border) {
+ wp->w_redr_border = true;
+ }
+ was_resized = true;
+ } else if (!want_allocation && has_allocation) {
+ // Single grid mode, all rendering will be redirected to default_grid.
+ // Only keep track of the size and offset of the window.
+ grid_free(grid_allocated);
+ grid_allocated->valid = false;
+ was_resized = true;
+ } else if (want_allocation && has_allocation && !wp->w_grid_alloc.valid) {
+ grid_invalidate(grid_allocated);
+ grid_allocated->valid = true;
+ }
+
+ grid->rows = rows;
+ grid->cols = cols;
+
+ if (want_allocation) {
+ grid->target = grid_allocated;
+ grid->row_offset = wp->w_winrow_off;
+ grid->col_offset = wp->w_wincol_off;
+ } else {
+ grid->target = &default_grid;
+ grid->row_offset = wp->w_winrow + wp->w_winrow_off;
+ grid->col_offset = wp->w_wincol + wp->w_wincol_off;
+ }
+
+ // send grid resize event if:
+ // - a grid was just resized
+ // - screen_resize was called and all grid sizes must be sent
+ // - the UI wants multigrid event (necessary)
+ if ((resizing_screen || was_resized) && want_allocation) {
+ ui_call_grid_resize(grid_allocated->handle,
+ grid_allocated->cols, grid_allocated->rows);
+ }
+}
+
+/// assign a handle to the grid. The grid need not be allocated.
+void grid_assign_handle(ScreenGrid *grid)
+{
+ static int last_grid_handle = DEFAULT_GRID_HANDLE;
+
+ // only assign a grid handle if not already
+ if (grid->handle == 0) {
+ grid->handle = ++last_grid_handle;
+ }
+}
diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h
index 2516ea52a7..a97a1c2c39 100644
--- a/src/nvim/grid_defs.h
+++ b/src/nvim/grid_defs.h
@@ -58,8 +58,8 @@ struct ScreenGrid {
int *dirty_col;
// the size of the allocated grid.
- int Rows;
- int Columns;
+ int rows;
+ int cols;
// The state of the grid is valid. Otherwise it needs to be redrawn.
bool valid;
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 9ab086f1ea..49549bcc26 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -162,7 +162,7 @@ void msg_grid_validate(void)
{
grid_assign_handle(&msg_grid);
bool should_alloc = msg_use_grid();
- if (should_alloc && (msg_grid.Rows != Rows || msg_grid.Columns != Columns
+ if (should_alloc && (msg_grid.rows != Rows || msg_grid.cols != Columns
|| !msg_grid.chars)) {
// TODO(bfredl): eventually should be set to "invalid". I e all callers
// will use the grid including clear to EOS if necessary.
@@ -174,9 +174,9 @@ void msg_grid_validate(void)
// Tricky: allow resize while pager is active
int pos = msg_scrolled ? msg_grid_pos : Rows - p_ch;
- ui_comp_put_grid(&msg_grid, pos, 0, msg_grid.Rows, msg_grid.Columns,
+ ui_comp_put_grid(&msg_grid, pos, 0, msg_grid.rows, msg_grid.cols,
false, true);
- ui_call_grid_resize(msg_grid.handle, msg_grid.Columns, msg_grid.Rows);
+ ui_call_grid_resize(msg_grid.handle, msg_grid.cols, msg_grid.rows);
msg_grid.throttled = false; // don't throttle in 'cmdheight' area
msg_scrolled_at_flush = msg_scrolled;
@@ -2320,10 +2320,10 @@ void msg_scroll_up(bool may_throttle)
if (msg_grid_pos > 0) {
msg_grid_set_pos(msg_grid_pos - 1, true);
} else {
- grid_del_lines(&msg_grid, 0, 1, msg_grid.Rows, 0, msg_grid.Columns);
+ grid_del_lines(&msg_grid, 0, 1, msg_grid.rows, 0, msg_grid.cols);
memmove(msg_grid.dirty_col, msg_grid.dirty_col + 1,
- (msg_grid.Rows - 1) * sizeof(*msg_grid.dirty_col));
- msg_grid.dirty_col[msg_grid.Rows - 1] = 0;
+ (msg_grid.rows - 1) * sizeof(*msg_grid.dirty_col));
+ msg_grid.dirty_col[msg_grid.rows - 1] = 0;
}
} else {
grid_del_lines(&msg_grid_adj, 0, 1, Rows, 0, Columns);
@@ -2356,7 +2356,7 @@ void msg_scroll_flush(void)
msg_grid.throttled = false;
int pos_delta = msg_grid_pos_at_flush - msg_grid_pos;
assert(pos_delta >= 0);
- int delta = MIN(msg_scrolled - msg_scrolled_at_flush, msg_grid.Rows);
+ int delta = MIN(msg_scrolled - msg_scrolled_at_flush, msg_grid.rows);
if (pos_delta > 0) {
ui_ext_msg_set_pos(msg_grid_pos, true);
@@ -2374,7 +2374,7 @@ void msg_scroll_flush(void)
for (int i = MAX(Rows - MAX(delta, 1), 0); i < Rows; i++) {
int row = i - msg_grid_pos;
assert(row >= 0);
- ui_line(&msg_grid, row, 0, msg_grid.dirty_col[row], msg_grid.Columns,
+ ui_line(&msg_grid, row, 0, msg_grid.dirty_col[row], msg_grid.cols,
HL_ATTR(HLF_MSG), false);
msg_grid.dirty_col[row] = 0;
}
@@ -2400,9 +2400,9 @@ void msg_reset_scroll(void)
clear_cmdline = true;
if (msg_grid.chars) {
// non-displayed part of msg_grid is considered invalid.
- for (int i = 0; i < MIN(msg_scrollsize(), msg_grid.Rows); i++) {
+ for (int i = 0; i < MIN(msg_scrollsize(), msg_grid.rows); i++) {
grid_clear_line(&msg_grid, msg_grid.line_offset[i],
- msg_grid.Columns, false);
+ msg_grid.cols, false);
}
}
} else {
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index ad17bfc8a9..8736c73080 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -159,16 +159,16 @@ retnomove:
fdc = win_fdccol_count(wp);
dragwin = NULL;
- if (row == -1 + wp->w_winbar_height) {
- on_winbar = !!wp->w_winbar_height;
+ if (row == -1) {
+ on_winbar = wp->w_winbar_height != 0;
return IN_OTHER_WIN | (on_winbar ? MOUSE_WINBAR : 0);
}
on_winbar = false;
// winpos and height may change in win_enter()!
- if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) {
+ if (grid == DEFAULT_GRID_HANDLE && row + wp->w_winbar_height >= wp->w_height) {
// In (or below) status line
- on_status_line = row - wp->w_height + 1;
+ on_status_line = row + wp->w_winbar_height - wp->w_height + 1;
dragwin = wp;
} else {
on_status_line = 0;
@@ -273,6 +273,9 @@ retnomove:
if (grid == 0) {
row -= curwin->w_grid_alloc.comp_row + curwin->w_grid.row_offset;
col -= curwin->w_grid_alloc.comp_col + curwin->w_grid.col_offset;
+ } else if (grid != DEFAULT_GRID_HANDLE) {
+ row -= curwin->w_grid.row_offset;
+ col -= curwin->w_grid.col_offset;
}
// When clicking beyond the end of the window, scroll the screen.
@@ -406,9 +409,6 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
if (win->w_p_rl) {
col = win->w_width_inner - 1 - col;
}
- if (win->w_winbar_height) {
- row -= win->w_winbar_height;
- }
lnum = win->w_topline;
@@ -509,7 +509,7 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
// exist.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp == fp->fr_win) {
- *rowp -= wp->w_winrow_off - wp->w_winbar_height;
+ *rowp -= wp->w_winbar_height;
return wp;
}
}
@@ -525,8 +525,8 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
win_T *wp = get_win_by_grid_handle(*gridp);
if (wp && wp->w_grid_alloc.chars
&& !(wp->w_floating && !wp->w_float_config.focusable)) {
- *rowp = MIN(*rowp - wp->w_grid.row_offset, wp->w_grid.Rows - 1);
- *colp = MIN(*colp - wp->w_grid.col_offset, wp->w_grid.Columns - 1);
+ *rowp = MIN(*rowp - wp->w_grid.row_offset, wp->w_grid.rows - 1);
+ *colp = MIN(*colp - wp->w_grid.col_offset, wp->w_grid.cols - 1);
return wp;
}
} else if (*gridp == 0) {
@@ -797,8 +797,8 @@ int mouse_check_fold(void)
wp = mouse_find_win(&click_grid, &click_row, &click_col);
if (wp && multigrid) {
- max_row = wp->w_grid_alloc.Rows;
- max_col = wp->w_grid_alloc.Columns;
+ max_row = wp->w_grid_alloc.rows;
+ max_col = wp->w_grid_alloc.cols;
}
if (wp && mouse_row >= 0 && mouse_row < max_row
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2ee6c175bb..61ac542fcf 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4049,18 +4049,6 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
// buf->b_p_swf
mf_close_file(curbuf, true); // remove the swap file
}
- } else if ((int *)varp == &p_terse) {
- // when 'terse' is set change 'shortmess'
- char *p = vim_strchr((char *)p_shm, SHM_SEARCH);
-
- // insert 's' in p_shm
- if (p_terse && p == NULL) {
- STRCPY(IObuff, p_shm);
- STRCAT(IObuff, "s");
- set_string_option_direct("shm", -1, IObuff, OPT_FREE, 0);
- } else if (!p_terse && p != NULL) { // remove 's' from p_shm
- STRMOVE(p, p + 1);
- }
} else if ((int *)varp == &p_paste) {
// when 'paste' is set or reset also change other options
paste_option_changed();
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index f5c7ae07bb..876acf2f87 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -557,7 +557,6 @@ static char *(p_rdb_values[]) = {
#define RDB_NODELTA 0x008
EXTERN long p_rdt; // 'redrawtime'
-EXTERN int p_remap; // 'remap'
EXTERN long p_re; // 'regexpengine'
EXTERN long p_report; // 'report'
EXTERN long p_pvh; // 'previewheight'
@@ -679,7 +678,6 @@ EXTERN int p_tr; ///< 'tagrelative'
EXTERN char_u *p_tags; ///< 'tags'
EXTERN int p_tgst; ///< 'tagstack'
EXTERN int p_tbidi; ///< 'termbidi'
-EXTERN int p_terse; ///< 'terse'
EXTERN int p_to; ///< 'tildeop'
EXTERN int p_timeout; ///< 'timeout'
EXTERN long p_tm; ///< 'timeoutlen'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index eb92d47fc8..809d4ab48b 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1911,9 +1911,9 @@ return {
},
{
full_name='remap',
- short_desc=N_("mappings to work recursively"),
+ short_desc=N_("No description"),
type='bool', scope={'global'},
- varname='p_remap',
+ varname='p_force_on',
defaults={if_true=true}
},
{
@@ -2529,9 +2529,9 @@ return {
},
{
full_name='terse',
- short_desc=N_("hides notification of search wrap"),
+ short_desc=N_("No description"),
type='bool', scope={'global'},
- varname='p_terse',
+ varname='p_force_off',
defaults={if_true=false}
},
{
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index c99d2869da..ac21b32a3e 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -19,6 +19,7 @@
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/os/input.h"
+#include "nvim/screen.h"
#include "nvim/state.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -178,15 +179,7 @@ void os_breakcheck(void)
return;
}
- int save_us = updating_screen;
- // We do not want screen_resize() to redraw here.
- // TODO(bfredl): we are already special casing redraw events, is this
- // hack still needed?
- updating_screen++;
-
loop_poll_events(&main_loop, 0);
-
- updating_screen = save_us;
}
#define BREAKCHECK_SKIP 1000
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index c5c1d87919..9525a84e62 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -429,9 +429,9 @@ void pum_redraw(void)
must_redraw_pum = false;
if (!pum_grid.chars
- || pum_grid.Rows != pum_height || pum_grid.Columns != grid_width) {
+ || pum_grid.rows != pum_height || pum_grid.cols != grid_width) {
grid_alloc(&pum_grid, pum_height, grid_width, !invalid_grid, false);
- ui_call_grid_resize(pum_grid.handle, pum_grid.Columns, pum_grid.Rows);
+ ui_call_grid_resize(pum_grid.handle, pum_grid.cols, pum_grid.rows);
} else if (invalid_grid) {
grid_invalidate(&pum_grid);
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b2490fb9c5..86dbf532a7 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -132,10 +132,6 @@
static match_T search_hl; // used for 'hlsearch' highlight matching
-StlClickDefinition *tab_page_click_defs = NULL;
-
-long tab_page_click_defs_size = 0;
-
// for line_putchar. Contains the state that needs to be remembered from
// putting one character to the next.
typedef struct {
@@ -382,9 +378,9 @@ int update_screen(int type)
int valid = MAX(Rows - msg_scrollsize(), 0);
if (msg_grid.chars) {
// non-displayed part of msg_grid is considered invalid.
- for (int i = 0; i < MIN(msg_scrollsize(), msg_grid.Rows); i++) {
+ for (int i = 0; i < MIN(msg_scrollsize(), msg_grid.rows); i++) {
grid_clear_line(&msg_grid, msg_grid.line_offset[i],
- msg_grid.Columns, false);
+ msg_grid.cols, false);
}
}
if (msg_use_msgsep()) {
@@ -607,8 +603,6 @@ int update_screen(int type)
pum_redraw();
}
- send_grid_resize = false;
-
/* Reset b_mod_set flags. Going through all windows is probably faster
* than going through all buffers (there could be many buffers). */
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
@@ -757,7 +751,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
// Window is zero-height: Only need to draw the separator
- if (wp->w_grid.Rows == 0) {
+ if (wp->w_grid.rows == 0) {
// draw the horizontal separator below this window
draw_hsep_win(wp);
draw_sep_connectors_win(wp);
@@ -766,7 +760,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
// Window is zero-width: Only need to draw the separator.
- if (wp->w_grid.Columns == 0) {
+ if (wp->w_grid.cols == 0) {
// draw the vertical separator right of this window
draw_vsep_win(wp);
draw_sep_connectors_win(wp);
@@ -965,7 +959,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
j = 0;
for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ln++) {
j++;
- if (j >= wp->w_grid.Rows - 2) {
+ if (j >= wp->w_grid.rows - 2) {
break;
}
(void)hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
@@ -973,13 +967,13 @@ static void win_update(win_T *wp, DecorProviders *providers)
} else {
j = wp->w_lines[0].wl_lnum - wp->w_topline;
}
- if (j < wp->w_grid.Rows - 2) { // not too far off
+ if (j < wp->w_grid.rows - 2) { // not too far off
i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1);
// insert extra lines for previously invisible filler lines
if (wp->w_lines[0].wl_lnum != wp->w_topline) {
i += win_get_fill(wp, wp->w_lines[0].wl_lnum) - wp->w_old_topfill;
}
- if (i != 0 && i < wp->w_grid.Rows - 2) { // less than a screen off
+ if (i != 0 && i < wp->w_grid.rows - 2) { // less than a screen off
// Try to insert the correct number of lines.
// If not the last window, delete the lines at the bottom.
// win_ins_lines may fail when the terminal can't do it.
@@ -992,8 +986,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Move the entries that were scrolled, disable
// the entries for the lines to be redrawn.
- if ((wp->w_lines_valid += j) > wp->w_grid.Rows) {
- wp->w_lines_valid = wp->w_grid.Rows;
+ if ((wp->w_lines_valid += j) > wp->w_grid.rows) {
+ wp->w_lines_valid = wp->w_grid.rows;
}
for (idx = wp->w_lines_valid; idx - j >= 0; idx--) {
wp->w_lines[idx] = wp->w_lines[idx - j];
@@ -1046,7 +1040,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
row -= wp->w_topfill;
if (row > 0) {
win_scroll_lines(wp, 0, -row);
- bot_start = wp->w_grid.Rows - row;
+ bot_start = wp->w_grid.rows - row;
}
if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0) {
/*
@@ -1062,7 +1056,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
/* stop at line that didn't fit, unless it is still
* valid (no lines deleted) */
if (row > 0 && bot_start + row
- + (int)wp->w_lines[j].wl_size > wp->w_grid.Rows) {
+ + (int)wp->w_lines[j].wl_size > wp->w_grid.rows) {
wp->w_lines_valid = idx + 1;
break;
}
@@ -1087,18 +1081,18 @@ static void win_update(win_T *wp, DecorProviders *providers)
// When starting redraw in the first line, redraw all lines.
if (mid_start == 0) {
- mid_end = wp->w_grid.Rows;
+ mid_end = wp->w_grid.rows;
}
} else {
// Not VALID or INVERTED: redraw all lines.
mid_start = 0;
- mid_end = wp->w_grid.Rows;
+ mid_end = wp->w_grid.rows;
}
if (type == SOME_VALID) {
// SOME_VALID: redraw all lines.
mid_start = 0;
- mid_end = wp->w_grid.Rows;
+ mid_end = wp->w_grid.rows;
type = NOT_VALID;
}
@@ -1285,7 +1279,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
}
srow += mid_start;
- mid_end = wp->w_grid.Rows;
+ mid_end = wp->w_grid.rows;
for (; idx < wp->w_lines_valid; idx++) { // find end
if (wp->w_lines[idx].wl_valid
&& wp->w_lines[idx].wl_lnum >= to + 1) {
@@ -1338,7 +1332,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
for (;;) {
/* stop updating when reached the end of the window (check for _past_
* the end of the window is at the end of the loop) */
- if (row == wp->w_grid.Rows) {
+ if (row == wp->w_grid.rows) {
didline = true;
break;
}
@@ -1443,7 +1437,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
new_rows += plines_win(wp, l, true);
}
j++;
- if (new_rows > wp->w_grid.Rows - row - 2) {
+ if (new_rows > wp->w_grid.rows - row - 2) {
// it's getting too much, must redraw the rest
new_rows = 9999;
break;
@@ -1455,17 +1449,17 @@ static void win_update(win_T *wp, DecorProviders *providers)
* remaining text or scrolling fails, must redraw the
* rest. If scrolling works, must redraw the text
* below the scrolled text. */
- if (row - xtra_rows >= wp->w_grid.Rows - 2) {
+ if (row - xtra_rows >= wp->w_grid.rows - 2) {
mod_bot = MAXLNUM;
} else {
win_scroll_lines(wp, row, xtra_rows);
- bot_start = wp->w_grid.Rows + xtra_rows;
+ bot_start = wp->w_grid.rows + xtra_rows;
}
} else if (xtra_rows > 0) {
/* May scroll text down. If there is not enough
* remaining text of scrolling fails, must redraw the
* rest. */
- if (row + xtra_rows >= wp->w_grid.Rows - 2) {
+ if (row + xtra_rows >= wp->w_grid.rows - 2) {
mod_bot = MAXLNUM;
} else {
win_scroll_lines(wp, row + old_rows, xtra_rows);
@@ -1493,7 +1487,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_lines[j] = wp->w_lines[i];
// stop at a line that won't fit
if (x + (int)wp->w_lines[j].wl_size
- > wp->w_grid.Rows) {
+ > wp->w_grid.rows) {
wp->w_lines_valid = j + 1;
break;
}
@@ -1507,8 +1501,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
// move entries in w_lines[] downwards
j -= i;
wp->w_lines_valid += j;
- if (wp->w_lines_valid > wp->w_grid.Rows) {
- wp->w_lines_valid = wp->w_grid.Rows;
+ if (wp->w_lines_valid > wp->w_grid.rows) {
+ wp->w_lines_valid = wp->w_grid.rows;
}
for (i = wp->w_lines_valid; i - j >= idx; i--) {
wp->w_lines[i] = wp->w_lines[i - j];
@@ -1539,11 +1533,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
&& wp->w_lines[idx].wl_lnum == lnum
&& lnum > wp->w_topline
&& !(dy_flags & (DY_LASTLINE | DY_TRUNCATE))
- && srow + wp->w_lines[idx].wl_size > wp->w_grid.Rows
+ && srow + wp->w_lines[idx].wl_size > wp->w_grid.rows
&& win_get_fill(wp, lnum) == 0) {
// This line is not going to fit. Don't draw anything here,
// will draw "@ " lines below.
- row = wp->w_grid.Rows + 1;
+ row = wp->w_grid.rows + 1;
} else {
prepare_search_hl(wp, &search_hl, lnum);
// Let the syntax stuff know we skipped a few lines.
@@ -1554,7 +1548,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Display one line
row = win_line(wp, lnum, srow,
- foldinfo.fi_lines ? srow : wp->w_grid.Rows,
+ foldinfo.fi_lines ? srow : wp->w_grid.rows,
mod_top == 0, false, foldinfo, &line_providers);
if (foldinfo.fi_lines == 0) {
@@ -1573,7 +1567,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_lines[idx].wl_lnum = lnum;
wp->w_lines[idx].wl_valid = true;
- if (row > wp->w_grid.Rows) { // past end of grid
+ if (row > wp->w_grid.rows) { // past end of grid
// we may need the size of that too long line later on
if (dollar_vcol == -1) {
wp->w_lines[idx].wl_size = plines_win(wp, lnum, true);
@@ -1591,13 +1585,13 @@ static void win_update(win_T *wp, DecorProviders *providers)
// 'relativenumber' set and cursor moved vertically: The
// text doesn't need to be drawn, but the number column does.
foldinfo_T info = fold_info(wp, lnum);
- (void)win_line(wp, lnum, srow, wp->w_grid.Rows, true, true,
+ (void)win_line(wp, lnum, srow, wp->w_grid.rows, true, true,
info, &line_providers);
}
// This line does not need to be drawn, advance to the next one.
row += wp->w_lines[idx++].wl_size;
- if (row > wp->w_grid.Rows) { // past end of screen
+ if (row > wp->w_grid.rows) { // past end of screen
break;
}
lnum = wp->w_lines[idx - 1].wl_lastlnum + 1;
@@ -1645,41 +1639,41 @@ static void win_update(win_T *wp, DecorProviders *providers)
* Don't overwrite it, it can be edited.
*/
wp->w_botline = lnum + 1;
- } else if (win_get_fill(wp, lnum) >= wp->w_grid.Rows - srow) {
+ } else if (win_get_fill(wp, lnum) >= wp->w_grid.rows - srow) {
// Window ends in filler lines.
wp->w_botline = lnum;
- wp->w_filler_rows = wp->w_grid.Rows - srow;
+ wp->w_filler_rows = wp->w_grid.rows - srow;
} else if (dy_flags & DY_TRUNCATE) { // 'display' has "truncate"
- int scr_row = wp->w_grid.Rows - 1;
+ int scr_row = wp->w_grid.rows - 1;
// Last line isn't finished: Display "@@@" in the last screen line.
- grid_puts_len(&wp->w_grid, (char_u *)"@@", MIN(wp->w_grid.Columns, 2), scr_row, 0, at_attr);
+ grid_puts_len(&wp->w_grid, (char_u *)"@@", MIN(wp->w_grid.cols, 2), scr_row, 0, at_attr);
- grid_fill(&wp->w_grid, scr_row, scr_row + 1, 2, wp->w_grid.Columns,
+ grid_fill(&wp->w_grid, scr_row, scr_row + 1, 2, wp->w_grid.cols,
'@', ' ', at_attr);
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline"
- int start_col = wp->w_grid.Columns - 3;
+ int start_col = wp->w_grid.cols - 3;
// Last line isn't finished: Display "@@@" at the end.
- grid_fill(&wp->w_grid, wp->w_grid.Rows - 1, wp->w_grid.Rows,
- MAX(start_col, 0), wp->w_grid.Columns, '@', '@', at_attr);
+ grid_fill(&wp->w_grid, wp->w_grid.rows - 1, wp->w_grid.rows,
+ MAX(start_col, 0), wp->w_grid.cols, '@', '@', at_attr);
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else {
- win_draw_end(wp, '@', ' ', true, srow, wp->w_grid.Rows, HLF_AT);
+ win_draw_end(wp, '@', ' ', true, srow, wp->w_grid.rows, HLF_AT);
wp->w_botline = lnum;
}
} else {
if (eof) { // we hit the end of the file
wp->w_botline = buf->b_ml.ml_line_count + 1;
j = win_get_fill(wp, wp->w_botline);
- if (j > 0 && !wp->w_botfill && row < wp->w_grid.Rows) {
+ if (j > 0 && !wp->w_botfill && row < wp->w_grid.rows) {
// Display filler text below last line. win_line() will check
// for ml_line_count+1 and only draw filler lines
foldinfo_T info = FOLDINFO_INIT;
- row = win_line(wp, wp->w_botline, row, wp->w_grid.Rows,
+ row = win_line(wp, wp->w_botline, row, wp->w_grid.rows,
false, false, info, &line_providers);
}
} else if (dollar_vcol == -1) {
@@ -1688,7 +1682,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// make sure the rest of the screen is blank
// write the 'eob' character to rows that aren't part of the file.
- win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.Rows,
+ win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.rows,
HLF_EOB);
}
@@ -1773,8 +1767,8 @@ static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row,
{
int nn = off + width;
- if (nn > wp->w_grid.Columns) {
- nn = wp->w_grid.Columns;
+ if (nn > wp->w_grid.cols) {
+ nn = wp->w_grid.cols;
}
if (wp->w_p_rl) {
@@ -1823,7 +1817,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, i
grid_fill(&wp->w_grid, row, endrow, W_ENDCOL(wp) - 1 - n, W_ENDCOL(wp) - n,
c1, c2, attr);
} else {
- grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.Columns, c1, c2, attr);
+ grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.cols, c1, c2, attr);
}
set_empty_rows(wp, row);
@@ -1847,7 +1841,7 @@ static int compute_foldcolumn(win_T *wp, int col)
{
int fdc = win_fdccol_count(wp);
int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw;
- int wwidth = wp->w_grid.Columns;
+ int wwidth = wp->w_grid.cols;
if (fdc > wwidth - (col + wmw)) {
fdc = wwidth - (col + wmw);
@@ -2631,7 +2625,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
// Rightleft window: process the text in the normal direction, but put
// it in linebuf_char[off] from right to left. Start at the
// rightmost column of the window.
- col = grid->Columns - 1;
+ col = grid->cols - 1;
off += col;
}
@@ -2813,7 +2807,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (wp->w_p_rl) {
n_extra = col + 1;
} else {
- n_extra = grid->Columns - col;
+ n_extra = grid->cols - col;
}
char_attr = 0;
} else if (filler_todo > 0) {
@@ -2828,7 +2822,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (wp->w_p_rl) {
n_extra = col + 1;
} else {
- n_extra = grid->Columns - col;
+ n_extra = grid->cols - col;
}
char_attr = win_hl_attr(wp, HLF_DED);
}
@@ -2902,15 +2896,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
&& vcol >= (long)wp->w_virtcol)
|| (number_only && draw_state > WL_NR))
&& filler_todo <= 0) {
- draw_virt_text(wp, buf, win_col_offset, &col, grid->Columns, row);
- grid_put_linebuf(grid, row, 0, col, -grid->Columns, wp->w_p_rl, wp,
+ draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row);
+ grid_put_linebuf(grid, row, 0, col, -grid->cols, wp->w_p_rl, wp,
wp->w_hl_attr_normal, false);
// Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set.
if (wp->w_p_cuc) {
row = wp->w_cline_row + wp->w_cline_height;
} else {
- row = grid->Rows;
+ row = grid->rows;
}
break;
}
@@ -2938,19 +2932,19 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (draw_state == WL_LINE
&& has_fold
- && col < grid->Columns
+ && col < grid->cols
&& n_extra == 0
&& row == startrow) {
// fill rest of line with 'fold'
c_extra = wp->w_p_fcs_chars.fold;
c_final = NUL;
- n_extra = wp->w_p_rl ? (col + 1) : (grid->Columns - col);
+ n_extra = wp->w_p_rl ? (col + 1) : (grid->cols - col);
}
if (draw_state == WL_LINE
&& has_fold
- && col >= grid->Columns
+ && col >= grid->cols
&& n_extra != 0
&& row == startrow) {
// Truncate the folding.
@@ -3079,7 +3073,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
}
// If a double-width char doesn't fit display a '>' in the last column.
- if ((wp->w_p_rl ? (col <= 0) : (col >= grid->Columns - 1))
+ if ((wp->w_p_rl ? (col <= 0) : (col >= grid->cols - 1))
&& utf_char2cells(mb_c) == 2) {
c = '>';
mb_c = c;
@@ -3193,7 +3187,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
// last column; the character is displayed at the start of the
// next line.
if ((wp->w_p_rl ? (col <= 0) :
- (col >= grid->Columns - 1))
+ (col >= grid->cols - 1))
&& utf_char2cells(mb_c) == 2) {
c = '>';
mb_c = c;
@@ -3398,7 +3392,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
}
}
- if (c == TAB && n_extra + col > grid->Columns) {
+ if (c == TAB && n_extra + col > grid->cols) {
n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts,
wp->w_buffer->b_p_vts_array) - 1;
}
@@ -3601,7 +3595,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|| ((fromcol >= 0 || fromcol_prev >= 0)
&& tocol > vcol
&& VIsual_mode != Ctrl_V
- && (wp->w_p_rl ? (col >= 0) : (col < grid->Columns))
+ && (wp->w_p_rl ? (col >= 0) : (col < grid->cols))
&& !(noinvcur
&& lnum == wp->w_cursor.lnum
&& (colnr_T)vcol == wp->w_virtcol)))
@@ -3673,7 +3667,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
&& virtual_active()
&& tocol != MAXCOL
&& vcol < tocol
- && (wp->w_p_rl ? (col >= 0) : (col < grid->Columns))) {
+ && (wp->w_p_rl ? (col >= 0) : (col < grid->cols))) {
c = ' ';
ptr--; // put it back at the NUL
}
@@ -3755,7 +3749,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
&& conceal_cursor_line(wp)
&& (int)wp->w_virtcol <= vcol + n_skip) {
if (wp->w_p_rl) {
- wp->w_wcol = grid->Columns - col + boguscols - 1;
+ wp->w_wcol = grid->cols - col + boguscols - 1;
} else {
wp->w_wcol = col - boguscols;
}
@@ -3827,7 +3821,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
n = 1;
}
} else {
- if (col >= grid->Columns) {
+ if (col >= grid->cols) {
n = -1;
}
}
@@ -3895,7 +3889,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (((wp->w_p_cuc
&& (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off
&& (int)wp->w_virtcol <
- (long)grid->Columns * (row - startrow + 1) + v
+ (long)grid->cols * (row - startrow + 1) + v
&& lnum != wp->w_cursor.lnum)
|| draw_color_col || line_attr_lowprio || line_attr
|| diff_hlf != (hlf_T)0 || has_virttext)) {
@@ -3933,7 +3927,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
int col_stride = wp->w_p_rl ? -1 : 1;
- while (wp->w_p_rl ? col >= 0 : col < grid->Columns) {
+ while (wp->w_p_rl ? col >= 0 : col < grid->cols) {
schar_from_ascii(linebuf_char[off], ' ');
col += col_stride;
if (draw_color_col) {
@@ -3966,7 +3960,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
// terminal buffers may need to highlight beyond the end of the
// logical line
int n = wp->w_p_rl ? -1 : 1;
- while (col >= 0 && col < grid->Columns) {
+ while (col >= 0 && col < grid->cols) {
schar_from_ascii(linebuf_char[off], ' ');
linebuf_attr[off] = vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[vcol];
off += n;
@@ -3975,8 +3969,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
}
}
- draw_virt_text(wp, buf, win_col_offset, &col, grid->Columns, row);
- grid_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
+ draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row);
+ grid_put_linebuf(grid, row, 0, col, grid->cols, wp->w_p_rl, wp,
wp->w_hl_attr_normal, false);
row++;
@@ -4001,7 +3995,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
&& wp->w_p_list
&& !wp->w_p_wrap
&& filler_todo <= 0
- && (wp->w_p_rl ? col == 0 : col == grid->Columns - 1)
+ && (wp->w_p_rl ? col == 0 : col == grid->cols - 1)
&& !has_fold
&& (*ptr != NUL
|| lcs_eol_one > 0
@@ -4191,7 +4185,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
* At end of screen line and there is more to come: Display the line
* so far. If there is no more to display it is caught above.
*/
- if ((wp->w_p_rl ? (col < 0) : (col >= grid->Columns))
+ if ((wp->w_p_rl ? (col < 0) : (col >= grid->cols))
&& foldinfo.fi_lines == 0
&& (draw_state != WL_LINE
|| *ptr != NUL
@@ -4204,7 +4198,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
&& filler_todo <= 0 // Not drawing diff filler lines.
&& lcs_eol_one != -1 // Haven't printed the lcs_eol character.
&& row != endrow - 1 // Not the last line being displayed.
- && (grid->Columns == Columns // Window spans the width of the screen,
+ && (grid->cols == Columns // Window spans the width of the screen,
|| ui_has(kUIMultigrid)) // or has dedicated grid.
&& !wp->w_p_rl; // Not right-to-left.
@@ -4216,13 +4210,13 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
assert(i >= 0);
int offset = kv_A(virt_lines, i).left_col ? 0 : win_col_offset;
draw_virt_text_item(buf, offset, kv_A(virt_lines, i).line,
- kHlModeReplace, grid->Columns, offset);
+ kHlModeReplace, grid->cols, offset);
}
} else {
- draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->Columns, row);
+ draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row);
}
- grid_put_linebuf(grid, row, 0, draw_col, grid->Columns, wp->w_p_rl,
+ grid_put_linebuf(grid, row, 0, draw_col, grid->cols, wp->w_p_rl,
wp, wp->w_hl_attr_normal, wrap);
if (wrap) {
ScreenGrid *current_grid = grid;
@@ -4249,7 +4243,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
// When the window is too narrow draw all "@" lines.
if (draw_state != WL_LINE && filler_todo <= 0) {
- win_draw_end(wp, '@', ' ', true, row, wp->w_grid.Rows, HLF_AT);
+ win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT);
row = endrow;
}
@@ -4262,7 +4256,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
col = 0;
off = 0;
if (wp->w_p_rl) {
- col = grid->Columns - 1; // col is not used if breaking!
+ col = grid->cols - 1; // col is not used if breaking!
off += col;
}
@@ -5330,8 +5324,10 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
use_sandbox = was_set_insecurely(wp, "tabline", 0);
} else if (draw_winbar) {
stl = (char_u *)((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
- row = wp->w_winrow;
- col = wp->w_wincol;
+ row = -1; // row zero is first row of text
+ col = 0;
+ grid = &wp->w_grid;
+ grid_adjust(&grid, &row, &col);
fillchar = wp->w_p_fcs_chars.wbr;
attr = (wp == curwin) ? HL_ATTR(HLF_WBR) : HL_ATTR(HLF_WBRNC);
maxwidth = wp->w_width_inner;
@@ -5571,88 +5567,6 @@ void check_for_delay(bool check_msg_scroll)
}
}
-/// (Re)allocates a window grid if size changed while in ext_multigrid mode.
-/// Updates size, offsets and handle for the grid regardless.
-///
-/// If "doclear" is true, don't try to copy from the old grid rather clear the
-/// resized grid.
-void win_grid_alloc(win_T *wp)
-{
- ScreenGrid *grid = &wp->w_grid;
- ScreenGrid *grid_allocated = &wp->w_grid_alloc;
-
- int rows = wp->w_height_inner;
- int cols = wp->w_width_inner;
- int total_rows = wp->w_height_outer;
- int total_cols = wp->w_width_outer;
-
- bool want_allocation = ui_has(kUIMultigrid) || wp->w_floating;
- bool has_allocation = (grid_allocated->chars != NULL);
-
- if (grid->Rows != rows) {
- wp->w_lines_valid = 0;
- xfree(wp->w_lines);
- wp->w_lines = xcalloc(rows + 1, sizeof(wline_T));
- }
-
- int was_resized = false;
- if (want_allocation && (!has_allocation
- || grid_allocated->Rows != total_rows
- || grid_allocated->Columns != total_cols)) {
- grid_alloc(grid_allocated, total_rows, total_cols,
- wp->w_grid_alloc.valid, false);
- grid_allocated->valid = true;
- if (wp->w_floating && wp->w_float_config.border) {
- wp->w_redr_border = true;
- }
- was_resized = true;
- } else if (!want_allocation && has_allocation) {
- // Single grid mode, all rendering will be redirected to default_grid.
- // Only keep track of the size and offset of the window.
- grid_free(grid_allocated);
- grid_allocated->valid = false;
- was_resized = true;
- } else if (want_allocation && has_allocation && !wp->w_grid_alloc.valid) {
- grid_invalidate(grid_allocated);
- grid_allocated->valid = true;
- }
-
- grid->Rows = rows;
- grid->Columns = cols;
-
- wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height;
- wp->w_wincol_off = wp->w_border_adj[3];
-
- if (want_allocation) {
- grid->target = grid_allocated;
- grid->row_offset = wp->w_winrow_off;
- grid->col_offset = wp->w_wincol_off;
- } else {
- grid->target = &default_grid;
- grid->row_offset = wp->w_winrow + wp->w_winrow_off;
- grid->col_offset = wp->w_wincol + wp->w_wincol_off;
- }
-
- // send grid resize event if:
- // - a grid was just resized
- // - screen_resize was called and all grid sizes must be sent
- // - the UI wants multigrid event (necessary)
- if ((send_grid_resize || was_resized) && want_allocation) {
- ui_call_grid_resize(grid_allocated->handle,
- grid_allocated->Columns, grid_allocated->Rows);
- }
-}
-
-/// assign a handle to the grid. The grid need not be allocated.
-void grid_assign_handle(ScreenGrid *grid)
-{
- static int last_grid_handle = DEFAULT_GRID_HANDLE;
-
- // only assign a grid handle if not already
- if (grid->handle == 0) {
- grid->handle = ++last_grid_handle;
- }
-}
/// Resize the screen to Rows and Columns.
///
@@ -5660,7 +5574,7 @@ void grid_assign_handle(ScreenGrid *grid)
///
/// There may be some time between setting Rows and Columns and (re)allocating
/// default_grid arrays. This happens when starting up and when
-/// (manually) changing the shell size. Always use default_grid.Rows and
+/// (manually) changing the shell size. Always use default_grid.rows and
/// default_grid.Columns to access items in default_grid.chars[]. Use Rows
/// and Columns for positioning text etc. where the final size of the shell is
/// needed.
@@ -5681,8 +5595,8 @@ retry:
// when Rows and Columns have been set and we have started doing full
// screen stuff.
if ((default_grid.chars != NULL
- && Rows == default_grid.Rows
- && Columns == default_grid.Columns
+ && Rows == default_grid.rows
+ && Columns == default_grid.cols
)
|| Rows == 0
|| Columns == 0
@@ -5781,9 +5695,9 @@ void screenclear(void)
}
// blank out the default grid
- for (i = 0; i < default_grid.Rows; i++) {
+ for (i = 0; i < default_grid.rows; i++) {
grid_clear_line(&default_grid, default_grid.line_offset[i],
- default_grid.Columns, true);
+ default_grid.cols, true);
default_grid.line_wraps[i] = false;
}
@@ -5867,16 +5781,16 @@ void win_scroll_lines(win_T *wp, int row, int line_count)
}
// No lines are being moved, just draw over the entire area
- if (row + abs(line_count) >= wp->w_grid.Rows) {
+ if (row + abs(line_count) >= wp->w_grid.rows) {
return;
}
if (line_count < 0) {
grid_del_lines(&wp->w_grid, row, -line_count,
- wp->w_grid.Rows, 0, wp->w_grid.Columns);
+ wp->w_grid.rows, 0, wp->w_grid.cols);
} else {
grid_ins_lines(&wp->w_grid, row, line_count,
- wp->w_grid.Rows, 0, wp->w_grid.Columns);
+ wp->w_grid.rows, 0, wp->w_grid.cols);
}
}
@@ -5915,7 +5829,7 @@ void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
// Shift line_offset[] line_count down to reflect the inserted lines.
// Clear the inserted lines.
for (i = 0; i < line_count; i++) {
- if (width != grid->Columns) {
+ if (width != grid->cols) {
// need to copy part of a line
j = end - 1 - i;
while ((j -= line_count) >= row) {
@@ -5933,7 +5847,7 @@ void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
}
grid->line_offset[j + line_count] = temp;
grid->line_wraps[j + line_count] = false;
- grid_clear_line(grid, temp, grid->Columns, false);
+ grid_clear_line(grid, temp, grid->cols, false);
}
}
@@ -5964,7 +5878,7 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
// Now shift line_offset[] line_count up to reflect the deleted lines.
// Clear the inserted lines.
for (i = 0; i < line_count; i++) {
- if (width != grid->Columns) {
+ if (width != grid->cols) {
// need to copy part of a line
j = row + i;
while ((j += line_count) <= end - 1) {
@@ -5983,7 +5897,7 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
}
grid->line_offset[j - line_count] = temp;
grid->line_wraps[j - line_count] = false;
- grid_clear_line(grid, temp, grid->Columns, false);
+ grid_clear_line(grid, temp, grid->cols, false);
}
}
@@ -6824,11 +6738,9 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
/// Set dimensions of the Nvim application "shell".
void screen_resize(int width, int height)
{
- static bool recursive = false;
-
// Avoid recursiveness, can happen when setting the window size causes
// another window-changed signal.
- if (updating_screen || recursive) {
+ if (updating_screen || resizing_screen) {
return;
}
@@ -6850,7 +6762,7 @@ void screen_resize(int width, int height)
return;
}
- recursive = true;
+ resizing_screen = true;
Rows = height;
Columns = width;
@@ -6867,9 +6779,9 @@ void screen_resize(int width, int height)
send_grid_resize = true;
- /* The window layout used to be adjusted here, but it now happens in
- * screenalloc() (also invoked from screenclear()). That is because the
- * "recursive" check above may skip this, but not screenalloc(). */
+ /// The window layout used to be adjusted here, but it now happens in
+ /// screenalloc() (also invoked from screenclear()). That is because the
+ /// recursize "resizing_screen" check above may skip this, but not screenalloc().
if (State != MODE_ASKMORE && State != MODE_EXTERNCMD && State != MODE_CONFIRM) {
screenclear();
@@ -6928,7 +6840,7 @@ void screen_resize(int width, int height)
}
ui_flush();
}
- recursive = false;
+ resizing_screen = false;
}
/// Check if the new Nvim application "shell" dimensions are valid.
diff --git a/src/nvim/screen.h b/src/nvim/screen.h
index 3afbaa5eb6..f3beeff8a9 100644
--- a/src/nvim/screen.h
+++ b/src/nvim/screen.h
@@ -49,14 +49,22 @@ typedef struct {
} StlClickRecord;
/// Array defining what should be done when tabline is clicked
-extern StlClickDefinition *tab_page_click_defs;
+EXTERN StlClickDefinition *tab_page_click_defs INIT(= NULL);
/// Size of the tab_page_click_defs array
-extern long tab_page_click_defs_size;
+EXTERN long tab_page_click_defs_size INIT(= 0);
#define W_ENDCOL(wp) ((wp)->w_wincol + (wp)->w_width)
#define W_ENDROW(wp) ((wp)->w_winrow + (wp)->w_height)
+// While redrawing the screen this flag is set. It means the screen size
+// ('lines' and 'rows') must not be changed.
+EXTERN bool updating_screen INIT(= 0);
+
+// While resizing the screen this flag is set.
+EXTERN bool resizing_screen INIT(= 0);
+
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "screen.h.generated.h"
#endif
diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim
index e0b05edf15..2fe3c448d6 100644
--- a/src/nvim/testdir/test_tagjump.vim
+++ b/src/nvim/testdir/test_tagjump.vim
@@ -1077,6 +1077,15 @@ Type number and <Enter> (q or empty cancels):
%bwipe
endfunc
+func Test_define_search()
+ " this was accessing freed memory
+ new
+ call setline(1, ['first line', '', '#define something 0'])
+ sil norm o0
+ sil! norm 
+ bwipe!
+endfunc
+
" Test for the 'taglength' option
func Test_tag_length()
set tags=Xtags
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 9e2d1f8e68..01583c032f 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -436,7 +436,7 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, int clearattr,
bool wrap)
{
- assert(0 <= row && row < grid->Rows);
+ assert(0 <= row && row < grid->rows);
LineFlags flags = wrap ? kLineFlagWrap : 0;
if (startcol == -1) {
startcol = 0;
@@ -453,7 +453,7 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
if (p_wd && !(rdb_flags & RDB_COMPOSITOR)) {
// If 'writedelay' is active, set the cursor to indicate what was drawn.
ui_call_grid_cursor_goto(grid->handle, row,
- MIN(clearcol, (int)grid->Columns - 1));
+ MIN(clearcol, (int)grid->cols - 1));
ui_call_flush();
uint64_t wd = (uint64_t)labs(p_wd);
os_microdelay(wd * 1000u, true);
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index f76158ff12..1dce84a1de 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -138,19 +138,19 @@ bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width,
// use it.
grid->comp_disabled = true;
compose_area(grid->comp_row, row,
- grid->comp_col, grid->comp_col + grid->Columns);
+ grid->comp_col, grid->comp_col + grid->cols);
if (grid->comp_col < col) {
compose_area(MAX(row, grid->comp_row),
- MIN(row + height, grid->comp_row + grid->Rows),
+ MIN(row + height, grid->comp_row + grid->rows),
grid->comp_col, col);
}
- if (col + width < grid->comp_col + grid->Columns) {
+ if (col + width < grid->comp_col + grid->cols) {
compose_area(MAX(row, grid->comp_row),
- MIN(row + height, grid->comp_row + grid->Rows),
- col + width, grid->comp_col + grid->Columns);
+ MIN(row + height, grid->comp_row + grid->rows),
+ col + width, grid->comp_col + grid->cols);
}
- compose_area(row + height, grid->comp_row + grid->Rows,
- grid->comp_col, grid->comp_col + grid->Columns);
+ compose_area(row + height, grid->comp_row + grid->rows,
+ grid->comp_col, grid->comp_col + grid->cols);
grid->comp_disabled = false;
}
grid->comp_row = row;
@@ -188,8 +188,8 @@ bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width,
grid->comp_index = insert_at;
}
if (moved && valid && ui_comp_should_draw()) {
- compose_area(grid->comp_row, grid->comp_row + grid->Rows,
- grid->comp_col, grid->comp_col + grid->Columns);
+ compose_area(grid->comp_row, grid->comp_row + grid->rows,
+ grid->comp_col, grid->comp_col + grid->cols);
}
return moved;
}
@@ -249,10 +249,10 @@ static void ui_comp_raise_grid(ScreenGrid *grid, size_t new_index)
for (size_t i = old_index; i < new_index; i++) {
ScreenGrid *grid2 = kv_A(layers, i);
int startcol = MAX(grid->comp_col, grid2->comp_col);
- int endcol = MIN(grid->comp_col + grid->Columns,
- grid2->comp_col + grid2->Columns);
+ int endcol = MIN(grid->comp_col + grid->cols,
+ grid2->comp_col + grid2->cols);
compose_area(MAX(grid->comp_row, grid2->comp_row),
- MIN(grid->comp_row + grid->Rows, grid2->comp_row + grid2->Rows),
+ MIN(grid->comp_row + grid->rows, grid2->comp_row + grid2->rows),
startcol, endcol);
}
}
@@ -279,7 +279,7 @@ static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle, Integer r, Int
}
}
- if (cursor_col >= default_grid.Columns || cursor_row >= default_grid.Rows) {
+ if (cursor_col >= default_grid.cols || cursor_row >= default_grid.rows) {
// TODO(bfredl): this happens with 'writedelay', refactor?
// abort();
return;
@@ -292,8 +292,8 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col)
for (ssize_t i = (ssize_t)kv_size(layers) - 1; i > 0; i--) {
ScreenGrid *grid = kv_A(layers, i);
if (grid->focusable
- && row >= grid->comp_row && row < grid->comp_row + grid->Rows
- && col >= grid->comp_col && col < grid->comp_col + grid->Columns) {
+ && row >= grid->comp_row && row < grid->comp_row + grid->rows
+ && col >= grid->comp_col && col < grid->comp_col + grid->cols) {
return grid;
}
}
@@ -315,7 +315,7 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlag
startcol--;
skipstart = 1;
}
- if (endcol < default_grid.Columns && (flags & kLineFlagInvalid)) {
+ if (endcol < default_grid.cols && (flags & kLineFlagInvalid)) {
endcol++;
skipend = 1;
}
@@ -337,8 +337,8 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlag
// first check to see if any grids have pending updates to width/height,
// to ensure that we don't accidentally put any characters into `linebuf`
// that have been invalidated.
- grid_width = MIN(g->Columns, g->comp_width);
- grid_height = MIN(g->Rows, g->comp_height);
+ grid_width = MIN(g->cols, g->comp_width);
+ grid_height = MIN(g->rows, g->comp_height);
if (g->comp_row > row || row >= g->comp_row + grid_height
|| g->comp_disabled) {
continue;
@@ -354,7 +354,7 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlag
assert(grid != NULL);
assert(until > col);
- assert(until <= default_grid.Columns);
+ assert(until <= default_grid.cols);
size_t n = (size_t)(until - col);
if (row == msg_sep_row && grid->comp_index <= msg_grid.comp_index) {
@@ -371,7 +371,7 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlag
+ (size_t)(col - grid->comp_col);
memcpy(linebuf + (col - startcol), grid->chars + off, n * sizeof(*linebuf));
memcpy(attrbuf + (col - startcol), grid->attrs + off, n * sizeof(*attrbuf));
- if (grid->comp_col + grid->Columns > until
+ if (grid->comp_col + grid->cols > until
&& grid->chars[off + n][0] == NUL) {
linebuf[until - 1 - startcol][0] = ' ';
linebuf[until - 1 - startcol][1] = '\0';
@@ -452,8 +452,8 @@ static void compose_debug(Integer startrow, Integer endrow, Integer startcol, In
return;
}
- endrow = MIN(endrow, default_grid.Rows);
- endcol = MIN(endcol, default_grid.Columns);
+ endrow = MIN(endrow, default_grid.rows);
+ endcol = MIN(endcol, default_grid.cols);
int attr = syn_id2attr(syn_id);
for (int row = (int)startrow; row < endrow; row++) {
@@ -480,8 +480,8 @@ static void debug_delay(Integer lines)
static void compose_area(Integer startrow, Integer endrow, Integer startcol, Integer endcol)
{
compose_debug(startrow, endrow, startcol, endcol, dbghl_recompose, true);
- endrow = MIN(endrow, default_grid.Rows);
- endcol = MIN(endcol, default_grid.Columns);
+ endrow = MIN(endrow, default_grid.rows);
+ endcol = MIN(endcol, default_grid.cols);
if (endcol <= startcol) {
return;
}
@@ -497,8 +497,8 @@ static void compose_area(Integer startrow, Integer endrow, Integer startcol, Int
void ui_comp_compose_grid(ScreenGrid *grid)
{
if (ui_comp_should_draw()) {
- compose_area(grid->comp_row, grid->comp_row + grid->Rows,
- grid->comp_col, grid->comp_col + grid->Columns);
+ compose_area(grid->comp_row, grid->comp_row + grid->rows,
+ grid->comp_col, grid->comp_col + grid->cols);
}
}
@@ -523,17 +523,17 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, Integer startcol
// TODO(bfredl): this should not really be necessary. But on some condition
// when resizing nvim, a window will be attempted to be drawn on the older
// and possibly larger global screen size.
- if (row >= default_grid.Rows) {
+ if (row >= default_grid.rows) {
DLOG("compositor: invalid row %" PRId64 " on grid %" PRId64, row, grid);
return;
}
- if (clearcol > default_grid.Columns) {
+ if (clearcol > default_grid.cols) {
DLOG("compositor: invalid last column %" PRId64 " on grid %" PRId64,
clearcol, grid);
- if (startcol >= default_grid.Columns) {
+ if (startcol >= default_grid.cols) {
return;
}
- clearcol = default_grid.Columns;
+ clearcol = default_grid.cols;
endcol = MIN(endcol, clearcol);
}
@@ -581,7 +581,7 @@ static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrol
}
if (row > msg_current_row && ui_comp_should_draw()) {
- compose_area(MAX(msg_current_row - 1, 0), row, 0, default_grid.Columns);
+ compose_area(MAX(msg_current_row - 1, 0), row, 0, default_grid.cols);
} else if (row < msg_current_row && ui_comp_should_draw()
&& msg_current_row < Rows) {
int delta = msg_current_row - (int)row;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 1bff5933ea..4076bb2531 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -515,9 +515,14 @@ wingotofile:
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0) {
break;
}
+
+ // Make a copy, if the line was changed it will be freed.
+ ptr = vim_strnsave(ptr, len);
+
find_pattern_in_path(ptr, 0, len, true, Prenum == 0,
type, Prenum1, ACTION_SPLIT, 1, MAXLNUM);
- curwin->w_set_curswant = TRUE;
+ xfree(ptr);
+ curwin->w_set_curswant = true;
break;
// Quickfix window only: view the result under the cursor in a new split.
@@ -6292,7 +6297,6 @@ void win_set_inner_size(win_T *wp)
}
wp->w_skipcol = 0;
wp->w_height_inner = height;
- wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height;
// There is no point in adjusting the scroll position when exiting. Some
// values might be invalid.
@@ -6320,11 +6324,13 @@ void win_set_inner_size(win_T *wp)
wp->w_height_outer = (wp->w_height_inner + win_extra_height(wp));
wp->w_width_outer = (wp->w_width_inner + win_extra_width(wp));
+ wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height;
+ wp->w_wincol_off = wp->w_border_adj[3];
}
static int win_extra_height(win_T *wp)
{
- return wp->w_border_adj[0] + wp->w_border_adj[2];
+ return wp->w_border_adj[0] + wp->w_border_adj[2] + wp->w_winbar_height;
}
static int win_extra_width(win_T *wp)
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index 41de308a2c..c08c411de1 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -230,6 +230,34 @@ describe('autocmd api', function()
}, meths.get_var("autocmd_args"))
end)
+
+ it('can receive arbitrary data', function()
+ local function test(data)
+ eq(data, exec_lua([[
+ local input = ...
+ local output
+ vim.api.nvim_create_autocmd("User", {
+ pattern = "Test",
+ callback = function(args)
+ output = args.data
+ end,
+ })
+
+ vim.api.nvim_exec_autocmds("User", {
+ pattern = "Test",
+ data = input,
+ })
+
+ return output
+ ]], data))
+ end
+
+ test("Hello")
+ test(42)
+ test(true)
+ test({ "list" })
+ test({ foo = "bar" })
+ end)
end)
describe('nvim_get_autocmds', function()
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index 97e41bbe83..c1b4777d16 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -1,9 +1,11 @@
local lfs = require('lfs')
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
local get_pathsep = helpers.get_pathsep
+local iswin = helpers.iswin
local eq = helpers.eq
local neq = helpers.neq
local funcs = helpers.funcs
@@ -106,8 +108,10 @@ describe(':mksession', function()
command('terminal')
command('cd '..cwd_dir)
command('mksession '..session_path)
- command('bd!')
- sleep(100) -- Make sure the process exits.
+ command('bdelete!')
+ if iswin() then
+ sleep(100) -- Make sure all child processes have exited.
+ end
command('qall!')
-- Create a new test instance of Nvim.
@@ -116,7 +120,50 @@ describe(':mksession', function()
local expected_cwd = cwd_dir..'/'..tab_dir
matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%'))
- command('bd!')
- sleep(100) -- Make sure the process exits.
+ command('bdelete!')
+ if iswin() then
+ sleep(100) -- Make sure all child processes have exited.
+ end
+ end)
+
+ it('restores CWD for :terminal buffer at root directory #16988', function()
+ if iswin() then
+ pending('N/A for Windows')
+ return
+ end
+
+ local screen
+ local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
+ local session_path = cwd_dir..'/'..session_file
+
+ screen = Screen.new(50, 6)
+ screen:attach({rgb=false})
+ local expected_screen = [[
+ ^/ |
+ |
+ [Process exited 0] |
+ |
+ |
+ |
+ ]]
+
+ command('cd /')
+ command('terminal echo $PWD')
+
+ -- Verify that the terminal's working directory is "/".
+ screen:expect(expected_screen)
+
+ command('cd '..cwd_dir)
+ command('mksession '..session_path)
+ command('qall!')
+
+ -- Create a new test instance of Nvim.
+ clear()
+ screen = Screen.new(50, 6)
+ screen:attach({rgb=false})
+ command('silent source '..session_path)
+
+ -- Verify that the terminal's working directory is "/".
+ screen:expect(expected_screen)
end)
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 4cb7636825..6c961eff7d 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -18,6 +18,7 @@ local NIL = helpers.NIL
local read_file = require('test.helpers').read_file
local write_file = require('test.helpers').write_file
local isCI = helpers.isCI
+local meths = helpers.meths
-- Use these to get access to a coroutine so that I can run async tests and use
-- yield.
@@ -341,6 +342,43 @@ describe('LSP', function()
}
end)
+ it('should fire autocommands on attach and detach', function()
+ local client
+ test_rpc_server {
+ test_name = "basic_init";
+ on_setup = function()
+ exec_lua [[
+ BUFFER = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_create_autocmd('LspAttach', {
+ callback = function(args)
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ vim.g.lsp_attached = client.name
+ end,
+ })
+ vim.api.nvim_create_autocmd('LspDetach', {
+ callback = function(args)
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+ vim.g.lsp_detached = client.name
+ end,
+ })
+ ]]
+ end;
+ on_init = function(_client)
+ client = _client
+ eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
+ client.notify('finish')
+ end;
+ on_handler = function(_, _, ctx)
+ if ctx.method == 'finish' then
+ eq('basic_init', meths.get_var('lsp_attached'))
+ exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
+ eq('basic_init', meths.get_var('lsp_detached'))
+ client.stop()
+ end
+ end;
+ }
+ end)
+
it('client should return settings via workspace/configuration handler', function()
local expected_handlers = {
{NIL, {}, {method="shutdown", client_id=1}};
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 7ab00e74d9..ca5e269f92 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -6627,7 +6627,7 @@ describe('float window', function()
it("left drag changes visual selection in float window", function()
local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar'})
+ meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
meths.open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=5})
if multigrid then
screen:expect{grid=[[
@@ -6651,12 +6651,12 @@ describe('float window', function()
## grid 5
{1:foo }|
{1:bar }|
- {2:~ }|
+ {1:baz }|
]], 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 = 2};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3};
}}
meths.input_mouse('left', 'press', '', 5, 0, 0)
screen:expect{grid=[[
@@ -6680,12 +6680,12 @@ describe('float window', function()
## grid 5
{1:^foo }|
{1:bar }|
- {2:~ }|
+ {1:baz }|
]], 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 = 2};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3};
}}
meths.input_mouse('left', 'drag', '', 5, 1, 2)
screen:expect{grid=[[
@@ -6709,12 +6709,12 @@ describe('float window', function()
## grid 5
{27:foo}{1: }|
{27:ba}{1:^r }|
- {2:~ }|
+ {1:baz }|
]], 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 = 2};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3};
}}
else
screen:expect{grid=[[
@@ -6722,7 +6722,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:foo }{0: }|
{0:~ }{1:bar }{0: }|
- {0:~ }{2:~ }{0: }|
+ {0:~ }{1:baz }{0: }|
{0:~ }|
|
]]}
@@ -6733,7 +6733,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^foo }{0: }|
{0:~ }{1:bar }{0: }|
- {0:~ }{2:~ }{0: }|
+ {0:~ }{1:baz }{0: }|
{0:~ }|
|
]]}
@@ -6744,7 +6744,269 @@ describe('float window', function()
{0:~ }|
{0:~ }{27:foo}{1: }{0: }|
{0:~ }{27:ba}{1:^r }{0: }|
- {0:~ }{2:~ }{0: }|
+ {0:~ }{1:baz }{0: }|
+ {0:~ }|
+ {3:-- VISUAL --} |
+ ]]}
+ end
+ end)
+
+ it("left drag changes visual selection in float window with border", function()
+ local buf = meths.create_buf(false,false)
+ meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
+ meths.open_win(buf, false, {relative='editor', width=20, height=3, row=0, col=5, border='single'})
+ 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 5
+ {5:┌────────────────────┐}|
+ {5:│}{1:foo }{5:│}|
+ {5:│}{1:bar }{5:│}|
+ {5:│}{1:baz }{5:│}|
+ {5:└────────────────────┘}|
+ ]], 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};
+ }}
+ meths.input_mouse('left', 'press', '', 5, 1, 1)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 5
+ {5:┌────────────────────┐}|
+ {5:│}{1:^foo }{5:│}|
+ {5:│}{1:bar }{5:│}|
+ {5:│}{1:baz }{5:│}|
+ {5:└────────────────────┘}|
+ ]], 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};
+ }}
+ meths.input_mouse('left', 'drag', '', 5, 2, 3)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ {3:-- VISUAL --} |
+ ## grid 5
+ {5:┌────────────────────┐}|
+ {5:│}{27:foo}{1: }{5:│}|
+ {5:│}{27:ba}{1:^r }{5:│}|
+ {5:│}{1:baz }{5:│}|
+ {5:└────────────────────┘}|
+ ]], 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};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ {5:┌────────────────────┐} |
+ {0:~ }{5:│}{1:foo }{5:│}{0: }|
+ {0:~ }{5:│}{1:bar }{5:│}{0: }|
+ {0:~ }{5:│}{1:baz }{5:│}{0: }|
+ {0:~ }{5:└────────────────────┘}{0: }|
+ {0:~ }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'press', '', 0, 1, 6)
+ screen:expect{grid=[[
+ {5:┌────────────────────┐} |
+ {0:~ }{5:│}{1:^foo }{5:│}{0: }|
+ {0:~ }{5:│}{1:bar }{5:│}{0: }|
+ {0:~ }{5:│}{1:baz }{5:│}{0: }|
+ {0:~ }{5:└────────────────────┘}{0: }|
+ {0:~ }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'drag', '', 0, 2, 8)
+ screen:expect{grid=[[
+ {5:┌────────────────────┐} |
+ {0:~ }{5:│}{27:foo}{1: }{5:│}{0: }|
+ {0:~ }{5:│}{27:ba}{1:^r }{5:│}{0: }|
+ {0:~ }{5:│}{1:baz }{5:│}{0: }|
+ {0:~ }{5:└────────────────────┘}{0: }|
+ {0:~ }|
+ {3:-- VISUAL --} |
+ ]]}
+ end
+ end)
+
+ it("left drag changes visual selection in float window with winbar", function()
+ local buf = meths.create_buf(false,false)
+ meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
+ local float_win = meths.open_win(buf, false, {relative='editor', width=20, height=4, row=1, col=5})
+ meths.win_set_option(float_win, 'winbar', 'floaty bar')
+ 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 5
+ {3:floaty bar }|
+ {1:foo }|
+ {1:bar }|
+ {1:baz }|
+ ]], 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};
+ }}
+ meths.input_mouse('left', 'press', '', 5, 1, 0)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 5
+ {3:floaty bar }|
+ {1:^foo }|
+ {1:bar }|
+ {1:baz }|
+ ]], 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};
+ }}
+ meths.input_mouse('left', 'drag', '', 5, 2, 2)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ {3:-- VISUAL --} |
+ ## grid 5
+ {3:floaty bar }|
+ {27:foo}{1: }|
+ {27:ba}{1:^r }|
+ {1:baz }|
+ ]], 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};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }{3:floaty bar }{0: }|
+ {0:~ }{1:foo }{0: }|
+ {0:~ }{1:bar }{0: }|
+ {0:~ }{1:baz }{0: }|
+ {0:~ }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'press', '', 0, 2, 5)
+ screen:expect{grid=[[
+ |
+ {0:~ }{3:floaty bar }{0: }|
+ {0:~ }{1:^foo }{0: }|
+ {0:~ }{1:bar }{0: }|
+ {0:~ }{1:baz }{0: }|
+ {0:~ }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'drag', '', 0, 3, 7)
+ screen:expect{grid=[[
+ |
+ {0:~ }{3:floaty bar }{0: }|
+ {0:~ }{27:foo}{1: }{0: }|
+ {0:~ }{27:ba}{1:^r }{0: }|
+ {0:~ }{1:baz }{0: }|
{0:~ }|
{3:-- VISUAL --} |
]]}
@@ -7591,6 +7853,53 @@ describe('float window', function()
]]}
end
end)
+
+ it('can use winbar', function()
+ local buf = meths.create_buf(false,false)
+ local win1 = meths.open_win(buf, false, {relative='editor', width=15, height=3, row=1, col=5})
+ meths.win_set_option(win1, 'winbar', 'floaty bar')
+
+ 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
+ {3:floaty bar }|
+ {1: }|
+ {2:~ }|
+ ]], 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};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }{3:floaty bar }{0: }|
+ {0:~ }{1: }{0: }|
+ {0:~ }{2:~ }{0: }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end
+ end)
end
describe('with ext_multigrid', function()
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index 20e8821009..b30aa67fd3 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -1915,7 +1915,7 @@ describe('ext_multigrid', function()
{1:~ }|
]]}
- meths.input_mouse('left', 'press', '', 1,6, 20)
+ meths.input_mouse('left', 'press', '', 1, 6, 20)
-- TODO(bfredl): "batching" input_mouse is formally not supported yet.
-- Normally it should work fine in async context when nvim is not blocked,
-- but add a poke_eventloop be sure.
@@ -2092,7 +2092,6 @@ describe('ext_multigrid', function()
{1:~ }|
{1:~ }|
]]}
-
end)
it('has viewport information', function()
@@ -2369,4 +2368,223 @@ describe('ext_multigrid', function()
[2] = {win = {id = 1000}, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11},
}}
end)
+
+ it('with winbar', function()
+ command 'split'
+ command 'setlocal winbar=very\\ bar'
+ screen:expect{grid=[[
+ ## grid 1
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ {11:[No Name] }|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ {12:[No Name] }|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {7:very bar }|
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {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};
+ }}
+ end)
+
+ it('with winbar dragging statusline with mouse works correctly', function()
+ meths.set_option('winbar', 'Set Up The Bars')
+ command('split')
+ screen:expect([[
+ ## grid 1
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ {11:[No Name] }|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ {12:[No Name] }|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ {7:Set Up The Bars }|
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {7:Set Up The Bars }|
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]])
+
+ meths.input_mouse('left', 'press', '', 1, 6, 20)
+ poke_eventloop()
+ meths.input_mouse('left', 'drag', '', 1, 7, 20)
+ screen:expect([[
+ ## grid 1
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ {11:[No Name] }|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ {12:[No Name] }|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ {7:Set Up The Bars }|
+ |
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {7:Set Up The Bars }|
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]])
+
+ meths.input_mouse('left', 'drag', '', 1, 4, 20)
+ screen:expect([[
+ ## grid 1
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ {11:[No Name] }|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ {12:[No Name] }|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ {7:Set Up The Bars }|
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {7:Set Up The Bars }|
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ ]])
+
+ meths.input_mouse('left', 'press', '', 1, 12, 10)
+ poke_eventloop()
+ meths.input_mouse('left', 'drag', '', 1, 10, 10)
+ screen:expect([[
+ ## grid 1
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ {11:[No Name] }|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ {12:[No Name] }|
+ [3:-----------------------------------------------------]|
+ [3:-----------------------------------------------------]|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ {7:Set Up The Bars }|
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ |
+ |
+ ## grid 4
+ {7:Set Up The Bars }|
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ ]])
+ eq(3, meths.get_option('cmdheight'))
+
+ meths.input_mouse('left', 'drag', '', 1, 12, 10)
+ screen:expect([[
+ ## grid 1
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|
+ {11:[No Name] }|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|
+ {12:[No Name] }|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ {7:Set Up The Bars }|
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {7:Set Up The Bars }|
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ ]])
+ eq(1, meths.get_option('cmdheight'))
+ end)
end)
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index e5cdc53b93..af7736293c 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -5,6 +5,7 @@ local command = helpers.command
local insert = helpers.insert
local meths = helpers.meths
local eq = helpers.eq
+local poke_eventloop = helpers.poke_eventloop
describe('winbar', function()
local screen
@@ -20,8 +21,9 @@ describe('winbar', function()
[4] = {bold = true, reverse = true},
[5] = {bold = true, foreground = Screen.colors.Red},
[6] = {foreground = Screen.colors.Blue},
+ [7] = {background = Screen.colors.LightGrey},
})
- command('set winbar=Set\\ Up\\ The\\ Bars')
+ meths.set_option('winbar', 'Set Up The Bars')
end)
it('works', function()
screen:expect([[
@@ -180,8 +182,9 @@ describe('winbar', function()
|
]])
end)
- it('sets correct position on mouse click', function()
- insert[[
+
+ it('mouse click and drag work correctly in buffer', function()
+ insert([[
line 1
line 2
line 3
@@ -189,10 +192,158 @@ describe('winbar', function()
line -42
line i
line sin(theta)
- line 8
- ]]
+ line 8]])
+
meths.input_mouse('left', 'press', '', 0, 5, 1)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ line 1 |
+ line 2 |
+ line 3 |
+ line 4 |
+ l^ine -42 |
+ line i |
+ line sin(theta) |
+ line 8 |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ |
+ ]])
eq({5, 1}, meths.win_get_cursor(0))
+
+ meths.input_mouse('left', 'drag', '', 0, 6, 2)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ line 1 |
+ line 2 |
+ line 3 |
+ line 4 |
+ l{7:ine -42} |
+ {7:li}^ne i |
+ line sin(theta) |
+ line 8 |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:-- VISUAL --} |
+ ]])
+ eq({6, 2}, meths.win_get_cursor(0))
+
+ meths.input_mouse('left', 'drag', '', 0, 1, 2)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ li^n{7:e 1} |
+ {7:line 2} |
+ {7:line 3} |
+ {7:line 4} |
+ {7:li}ne -42 |
+ line i |
+ line sin(theta) |
+ line 8 |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:-- VISUAL --} |
+ ]])
+ eq({1, 2}, meths.win_get_cursor(0))
+
+ meths.input_mouse('left', 'drag', '', 0, 0, 2)
+ screen:expect_unchanged()
+ eq({1, 2}, meths.win_get_cursor(0))
+ end)
+
+ it('dragging statusline with mouse works correctly', function()
+ command('split')
+ screen:expect([[
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ {1:Set Up The Bars }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ ]])
+
+ meths.input_mouse('left', 'press', '', 1, 5, 10)
+ poke_eventloop()
+ meths.input_mouse('left', 'drag', '', 1, 6, 10)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ {1:Set Up The Bars }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ ]])
+
+ meths.input_mouse('left', 'drag', '', 1, 4, 10)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ {1:Set Up The Bars }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ ]])
+
+ meths.input_mouse('left', 'press', '', 1, 11, 10)
+ poke_eventloop()
+ meths.input_mouse('left', 'drag', '', 1, 9, 10)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ {1:Set Up The Bars }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ |
+ |
+ ]])
+ eq(3, meths.get_option('cmdheight'))
+
+ meths.input_mouse('left', 'drag', '', 1, 11, 10)
+ screen:expect([[
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ {1:Set Up The Bars }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ ]])
+ eq(1, meths.get_option('cmdheight'))
end)
it('properly equalizes window height for window-local value', function()
command('set equalalways | set winbar= | setlocal winbar=a | split')