mirror of
https://github.com/neovim/neovim.git
synced 2026-05-23 21:30:11 +00:00
refactor: introduce nvim_on internally #39883
Problem: `nvim_create_autocmd` is too verbose and its `callback` requires extra "nesting". Solution: Introduce `nvim_on`. Start using it internally. Then we can get a feel for how it should look before making it public.
This commit is contained in:
@@ -57,6 +57,8 @@
|
||||
---
|
||||
--- The following properties are supported by default:
|
||||
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
--- @type table<string,fun(bufnr: integer, val: string, opts?: table)>
|
||||
local properties = {}
|
||||
|
||||
@@ -163,16 +165,12 @@ function properties.trim_trailing_whitespace(bufnr, val)
|
||||
'trim_trailing_whitespace must be either "true" or "false"'
|
||||
)
|
||||
if val == 'true' then
|
||||
vim.api.nvim_create_autocmd('BufWritePre', {
|
||||
group = 'nvim.editorconfig',
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
local view = vim.fn.winsaveview()
|
||||
vim.api.nvim_command('silent! undojoin')
|
||||
vim.api.nvim_command('silent keepjumps keeppatterns %s/\\s\\+$//e')
|
||||
vim.fn.winrestview(view)
|
||||
end,
|
||||
})
|
||||
nvim_on('BufWritePre', 'nvim.editorconfig', { buf = bufnr }, function()
|
||||
local view = vim.fn.winsaveview()
|
||||
vim.api.nvim_command('silent! undojoin')
|
||||
vim.api.nvim_command('silent keepjumps keeppatterns %s/\\s\\+$//e')
|
||||
vim.fn.winrestview(view)
|
||||
end)
|
||||
else
|
||||
vim.api.nvim_clear_autocmds({
|
||||
event = 'BufWritePre',
|
||||
@@ -192,14 +190,9 @@ function properties.insert_final_newline(bufnr, val)
|
||||
-- so only change 'endofline' right before writing the file
|
||||
local endofline = val == 'true'
|
||||
if vim.bo[bufnr].endofline ~= endofline then
|
||||
vim.api.nvim_create_autocmd('BufWritePre', {
|
||||
group = 'nvim.editorconfig',
|
||||
buf = bufnr,
|
||||
once = true,
|
||||
callback = function()
|
||||
vim.bo[bufnr].endofline = endofline
|
||||
end,
|
||||
})
|
||||
nvim_on('BufWritePre', 'nvim.editorconfig', { buf = bufnr, once = true }, function()
|
||||
vim.bo[bufnr].endofline = endofline
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -42,41 +43,21 @@ function M.enable()
|
||||
local group = api.nvim_create_augroup('matchparen', { clear = true })
|
||||
|
||||
-- Replace all matchparen autocommands
|
||||
api.nvim_create_autocmd({
|
||||
'CursorMoved',
|
||||
'CursorMovedI',
|
||||
'WinEnter',
|
||||
'WinScrolled',
|
||||
'TextChanged',
|
||||
'TextChangedI',
|
||||
}, {
|
||||
group = group,
|
||||
callback = function()
|
||||
nvim_on(
|
||||
{ 'CursorMoved', 'CursorMovedI', 'WinEnter', 'WinScrolled', 'TextChanged', 'TextChangedI' },
|
||||
group,
|
||||
function()
|
||||
M.highlight_matching_pair()
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('BufWinEnter', {
|
||||
group = group,
|
||||
callback = function()
|
||||
api.nvim_create_autocmd('SafeState', {
|
||||
group = group,
|
||||
once = true,
|
||||
callback = function()
|
||||
M.highlight_matching_pair()
|
||||
end,
|
||||
})
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd({
|
||||
'WinLeave',
|
||||
'BufLeave',
|
||||
'TextChangedP',
|
||||
}, {
|
||||
group = group,
|
||||
callback = function()
|
||||
M.remove_matches()
|
||||
end,
|
||||
})
|
||||
end
|
||||
)
|
||||
nvim_on('BufWinEnter', group, function()
|
||||
nvim_on('SafeState', group, { once = true }, function()
|
||||
M.highlight_matching_pair()
|
||||
end)
|
||||
end)
|
||||
nvim_on({ 'WinLeave', 'BufLeave', 'TextChangedP' }, group, function()
|
||||
M.remove_matches()
|
||||
end)
|
||||
|
||||
-- Define commands that will disable and enable the plugin.
|
||||
api.nvim_create_user_command('DoMatchParen', function()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
-- Default user-commands, autocmds, mappings, menus.
|
||||
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
--- Default user commands
|
||||
do
|
||||
vim.api.nvim_create_user_command('Inspect', function(cmd)
|
||||
@@ -547,15 +549,13 @@ do
|
||||
end
|
||||
|
||||
local nvim_popupmenu_augroup = vim.api.nvim_create_augroup('nvim.popupmenu', {})
|
||||
vim.api.nvim_create_autocmd('MenuPopup', {
|
||||
nvim_on('MenuPopup', nvim_popupmenu_augroup, {
|
||||
pattern = '*',
|
||||
group = nvim_popupmenu_augroup,
|
||||
desc = 'Mouse popup menu',
|
||||
-- nested = true,
|
||||
callback = function()
|
||||
enable_ctx_menu()
|
||||
end,
|
||||
})
|
||||
}, function()
|
||||
enable_ctx_menu()
|
||||
end)
|
||||
end
|
||||
|
||||
--- Default autocommands. See |default-autocmds|
|
||||
@@ -564,12 +564,9 @@ do
|
||||
if vim.v.vim_did_enter then
|
||||
require('vim._core.log').check_log_file()
|
||||
else
|
||||
vim.api.nvim_create_autocmd('VimEnter', {
|
||||
once = true,
|
||||
callback = function()
|
||||
require('vim._core.log').check_log_file()
|
||||
end,
|
||||
})
|
||||
nvim_on('VimEnter', nil, { once = true }, function()
|
||||
require('vim._core.log').check_log_file()
|
||||
end)
|
||||
end
|
||||
|
||||
local nvim_terminal_augroup = vim.api.nvim_create_augroup('nvim.terminal', {})
|
||||
@@ -581,21 +578,19 @@ do
|
||||
command = "if !exists('b:term_title')|call jobstart(matchstr(expand(\"<amatch>\"), '\\c\\mterm://\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), {'term': v:true, 'cwd': expand(get(matchlist(expand(\"<amatch>\"), '\\c\\mterm://\\(.\\{-}\\)//'), 1, ''))})",
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'TermClose' }, {
|
||||
group = nvim_terminal_augroup,
|
||||
nvim_on({ 'TermClose' }, nvim_terminal_augroup, {
|
||||
nested = true,
|
||||
desc = 'Automatically close terminal buffers when started with no arguments and exiting without an error',
|
||||
callback = function(ev)
|
||||
if vim.v.event.status ~= 0 then
|
||||
return
|
||||
end
|
||||
local info = vim.api.nvim_get_chan_info(vim.bo[ev.buf].channel)
|
||||
local argv = info.argv or {}
|
||||
if table.concat(argv, ' ') == vim.o.shell then
|
||||
vim.api.nvim_buf_delete(ev.buf, { force = true })
|
||||
end
|
||||
end,
|
||||
})
|
||||
}, function(ev)
|
||||
if vim.v.event.status ~= 0 then
|
||||
return
|
||||
end
|
||||
local info = vim.api.nvim_get_chan_info(vim.bo[ev.buf].channel)
|
||||
local argv = info.argv or {}
|
||||
if table.concat(argv, ' ') == vim.o.shell then
|
||||
vim.api.nvim_buf_delete(ev.buf, { force = true })
|
||||
end
|
||||
end)
|
||||
|
||||
local nvim_terminal_exitmsg_ns = vim.api.nvim_create_namespace('nvim.terminal.exitmsg')
|
||||
|
||||
@@ -609,95 +604,82 @@ do
|
||||
})
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd('TermClose', {
|
||||
group = nvim_terminal_augroup,
|
||||
nvim_on('TermClose', nvim_terminal_augroup, {
|
||||
nested = true,
|
||||
desc = 'Displays the "[Process exited]" virtual text',
|
||||
callback = function(ev)
|
||||
if not vim.api.nvim_buf_is_valid(ev.buf) then
|
||||
return
|
||||
end
|
||||
}, function(ev)
|
||||
if not vim.api.nvim_buf_is_valid(ev.buf) then
|
||||
return
|
||||
end
|
||||
|
||||
local buf = vim.bo[ev.buf]
|
||||
local pos = ev.data.pos ---@type integer
|
||||
local buf_has_exitmsg = #(
|
||||
vim.api.nvim_buf_get_extmarks(ev.buf, nvim_terminal_exitmsg_ns, 0, -1, {})
|
||||
) > 0
|
||||
local buf = vim.bo[ev.buf]
|
||||
local pos = ev.data.pos ---@type integer
|
||||
local buf_has_exitmsg = #(
|
||||
vim.api.nvim_buf_get_extmarks(ev.buf, nvim_terminal_exitmsg_ns, 0, -1, {})
|
||||
) > 0
|
||||
|
||||
-- `nvim_open_term` buffers do not have an attached 'channel'.
|
||||
local msg = buf.channel == 0 and '[Terminal closed]'
|
||||
or ('[Process exited %d]'):format(vim.v.event.status)
|
||||
-- `nvim_open_term` buffers do not have an attached 'channel'.
|
||||
local msg = buf.channel == 0 and '[Terminal closed]'
|
||||
or ('[Process exited %d]'):format(vim.v.event.status)
|
||||
|
||||
if buf.buftype ~= 'terminal' or buf_has_exitmsg then
|
||||
-- TermClose may be queued before TermOpen if process exits before `terminal_open` is called.
|
||||
-- Don't display the msg now, let TermOpen display it.
|
||||
vim.api.nvim_create_autocmd('TermOpen', {
|
||||
buf = ev.buf,
|
||||
once = true,
|
||||
callback = function()
|
||||
set_terminal_exitmsg(ev.buf, msg, pos)
|
||||
end,
|
||||
})
|
||||
return
|
||||
end
|
||||
set_terminal_exitmsg(ev.buf, msg, pos)
|
||||
end,
|
||||
})
|
||||
if buf.buftype ~= 'terminal' or buf_has_exitmsg then
|
||||
-- TermClose may be queued before TermOpen if process exits before `terminal_open` is called.
|
||||
-- Don't display the msg now, let TermOpen display it.
|
||||
nvim_on('TermOpen', nil, {
|
||||
buf = ev.buf,
|
||||
once = true,
|
||||
}, function()
|
||||
set_terminal_exitmsg(ev.buf, msg, pos)
|
||||
end)
|
||||
return
|
||||
end
|
||||
set_terminal_exitmsg(ev.buf, msg, pos)
|
||||
end)
|
||||
|
||||
vim.api.nvim_create_autocmd('TermRequest', {
|
||||
group = nvim_terminal_augroup,
|
||||
nvim_on('TermRequest', nvim_terminal_augroup, {
|
||||
desc = 'Handles OSC foreground/background color requests',
|
||||
callback = function(ev)
|
||||
--- @type integer
|
||||
local channel = vim.bo[ev.buf].channel
|
||||
if channel == 0 then
|
||||
return
|
||||
}, function(ev)
|
||||
--- @type integer
|
||||
local channel = vim.bo[ev.buf].channel
|
||||
if channel == 0 then
|
||||
return
|
||||
end
|
||||
local fg_request = ev.data.sequence == '\027]10;?'
|
||||
local bg_request = ev.data.sequence == '\027]11;?'
|
||||
if fg_request or bg_request then
|
||||
-- WARN: This does not return the actual foreground/background color,
|
||||
-- but rather returns:
|
||||
-- - fg=white/bg=black when Nvim option 'background' is 'dark'
|
||||
-- - fg=black/bg=white when Nvim option 'background' is 'light'
|
||||
local red, green, blue = 0, 0, 0
|
||||
local bg_option_dark = vim.o.background == 'dark'
|
||||
if (fg_request and bg_option_dark) or (bg_request and not bg_option_dark) then
|
||||
red, green, blue = 65535, 65535, 65535
|
||||
end
|
||||
local fg_request = ev.data.sequence == '\027]10;?'
|
||||
local bg_request = ev.data.sequence == '\027]11;?'
|
||||
if fg_request or bg_request then
|
||||
-- WARN: This does not return the actual foreground/background color,
|
||||
-- but rather returns:
|
||||
-- - fg=white/bg=black when Nvim option 'background' is 'dark'
|
||||
-- - fg=black/bg=white when Nvim option 'background' is 'light'
|
||||
local red, green, blue = 0, 0, 0
|
||||
local bg_option_dark = vim.o.background == 'dark'
|
||||
if (fg_request and bg_option_dark) or (bg_request and not bg_option_dark) then
|
||||
red, green, blue = 65535, 65535, 65535
|
||||
end
|
||||
local command = fg_request and 10 or 11
|
||||
local data = string.format(
|
||||
'\027]%d;rgb:%04x/%04x/%04x%s',
|
||||
command,
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
ev.data.terminator
|
||||
)
|
||||
vim.api.nvim_chan_send(channel, data)
|
||||
end
|
||||
end,
|
||||
})
|
||||
local command = fg_request and 10 or 11
|
||||
local data =
|
||||
string.format('\027]%d;rgb:%04x/%04x/%04x%s', command, red, green, blue, ev.data.terminator)
|
||||
vim.api.nvim_chan_send(channel, data)
|
||||
end
|
||||
end)
|
||||
|
||||
local nvim_terminal_prompt_ns = vim.api.nvim_create_namespace('nvim.terminal.prompt')
|
||||
vim.api.nvim_create_autocmd('TermRequest', {
|
||||
group = nvim_terminal_augroup,
|
||||
nvim_on('TermRequest', nvim_terminal_augroup, {
|
||||
desc = 'Mark shell prompts indicated by OSC 133 sequences for navigation',
|
||||
callback = function(ev)
|
||||
if string.match(ev.data.sequence, '^\027]133;A') then
|
||||
local lnum = ev.data.cursor[1] ---@type integer
|
||||
if lnum >= 1 then
|
||||
vim.api.nvim_buf_set_extmark(
|
||||
ev.buf,
|
||||
nvim_terminal_prompt_ns,
|
||||
lnum - 1,
|
||||
0,
|
||||
{ right_gravity = false }
|
||||
)
|
||||
end
|
||||
}, function(ev)
|
||||
if string.match(ev.data.sequence, '^\027]133;A') then
|
||||
local lnum = ev.data.cursor[1] ---@type integer
|
||||
if lnum >= 1 then
|
||||
vim.api.nvim_buf_set_extmark(
|
||||
ev.buf,
|
||||
nvim_terminal_prompt_ns,
|
||||
lnum - 1,
|
||||
0,
|
||||
{ right_gravity = false }
|
||||
)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
---@param ns integer
|
||||
---@param buf integer
|
||||
@@ -732,39 +714,37 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd('TermOpen', {
|
||||
group = nvim_terminal_augroup,
|
||||
nvim_on('TermOpen', nvim_terminal_augroup, {
|
||||
desc = 'Default settings for :terminal buffers',
|
||||
callback = function(ev)
|
||||
vim.bo[ev.buf].modifiable = false
|
||||
vim.bo[ev.buf].undolevels = -1
|
||||
vim.bo[ev.buf].scrollback = vim.o.scrollback < 0 and 10000 or math.max(1, vim.o.scrollback)
|
||||
vim.bo[ev.buf].textwidth = 0
|
||||
vim.wo[0][0].wrap = false
|
||||
vim.wo[0][0].list = false
|
||||
vim.wo[0][0].number = false
|
||||
vim.wo[0][0].relativenumber = false
|
||||
vim.wo[0][0].signcolumn = 'no'
|
||||
vim.wo[0][0].foldcolumn = '0'
|
||||
}, function(ev)
|
||||
vim.bo[ev.buf].modifiable = false
|
||||
vim.bo[ev.buf].undolevels = -1
|
||||
vim.bo[ev.buf].scrollback = vim.o.scrollback < 0 and 10000 or math.max(1, vim.o.scrollback)
|
||||
vim.bo[ev.buf].textwidth = 0
|
||||
vim.wo[0][0].wrap = false
|
||||
vim.wo[0][0].list = false
|
||||
vim.wo[0][0].number = false
|
||||
vim.wo[0][0].relativenumber = false
|
||||
vim.wo[0][0].signcolumn = 'no'
|
||||
vim.wo[0][0].foldcolumn = '0'
|
||||
|
||||
-- This is gross. Proper list options support when?
|
||||
local winhl = vim.o.winhighlight
|
||||
if winhl ~= '' then
|
||||
winhl = winhl .. ','
|
||||
end
|
||||
vim.wo[0][0].winhighlight = winhl .. 'StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC'
|
||||
-- This is gross. Proper list options support when?
|
||||
local winhl = vim.o.winhighlight
|
||||
if winhl ~= '' then
|
||||
winhl = winhl .. ','
|
||||
end
|
||||
vim.wo[0][0].winhighlight = winhl .. 'StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC'
|
||||
|
||||
vim.keymap.set({ 'n', 'x', 'o' }, '[[', function()
|
||||
jump_to_prompt(nvim_terminal_prompt_ns, 0, ev.buf, -vim.v.count1)
|
||||
end, { buf = ev.buf, desc = 'Jump [count] shell prompts backward' })
|
||||
vim.keymap.set({ 'n', 'x', 'o' }, ']]', function()
|
||||
jump_to_prompt(nvim_terminal_prompt_ns, 0, ev.buf, vim.v.count1)
|
||||
end, { buf = ev.buf, desc = 'Jump [count] shell prompts forward' })
|
||||
vim.keymap.set({ 'n', 'x', 'o' }, '[[', function()
|
||||
jump_to_prompt(nvim_terminal_prompt_ns, 0, ev.buf, -vim.v.count1)
|
||||
end, { buf = ev.buf, desc = 'Jump [count] shell prompts backward' })
|
||||
vim.keymap.set({ 'n', 'x', 'o' }, ']]', function()
|
||||
jump_to_prompt(nvim_terminal_prompt_ns, 0, ev.buf, vim.v.count1)
|
||||
end, { buf = ev.buf, desc = 'Jump [count] shell prompts forward' })
|
||||
|
||||
-- If the terminal buffer is being reused, clear the previous exit msg
|
||||
vim.api.nvim_buf_clear_namespace(ev.buf, nvim_terminal_exitmsg_ns, 0, -1)
|
||||
end,
|
||||
})
|
||||
-- If the terminal buffer is being reused, clear the previous exit msg
|
||||
vim.api.nvim_buf_clear_namespace(ev.buf, nvim_terminal_exitmsg_ns, 0, -1)
|
||||
end)
|
||||
|
||||
vim.api.nvim_create_autocmd('CmdwinEnter', {
|
||||
pattern = '[:>]',
|
||||
@@ -773,26 +753,24 @@ do
|
||||
command = 'syntax sync minlines=1 maxlines=1',
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd('SwapExists', {
|
||||
nvim_on('SwapExists', vim.api.nvim_create_augroup('nvim.swapfile', {}), {
|
||||
pattern = '*',
|
||||
desc = 'Skip the swapfile prompt when the swapfile is owned by a running Nvim process',
|
||||
group = vim.api.nvim_create_augroup('nvim.swapfile', {}),
|
||||
callback = function()
|
||||
local info = vim.fn.swapinfo(vim.v.swapname)
|
||||
local user = vim.uv.os_get_passwd().username
|
||||
local iswin = 1 == vim.fn.has('win32')
|
||||
if info.error or info.pid <= 0 or (not iswin and info.user ~= user) then
|
||||
vim.v.swapchoice = '' -- Show the prompt.
|
||||
return
|
||||
end
|
||||
vim.v.swapchoice = 'e' -- Choose "(E)dit".
|
||||
vim.notify(
|
||||
('W325: Ignoring swapfile from Nvim process %d'):format(info.pid),
|
||||
vim.log.levels.WARN,
|
||||
{ _truncate = true }
|
||||
)
|
||||
end,
|
||||
})
|
||||
}, function()
|
||||
local info = vim.fn.swapinfo(vim.v.swapname)
|
||||
local user = vim.uv.os_get_passwd().username
|
||||
local iswin = 1 == vim.fn.has('win32')
|
||||
if info.error or info.pid <= 0 or (not iswin and info.user ~= user) then
|
||||
vim.v.swapchoice = '' -- Show the prompt.
|
||||
return
|
||||
end
|
||||
vim.v.swapchoice = 'e' -- Choose "(E)dit".
|
||||
vim.notify(
|
||||
('W325: Ignoring swapfile from Nvim process %d'):format(info.pid),
|
||||
vim.log.levels.WARN,
|
||||
{ _truncate = true }
|
||||
)
|
||||
end)
|
||||
|
||||
-- Check if a TTY is attached
|
||||
local tty = nil
|
||||
@@ -824,14 +802,12 @@ do
|
||||
--- @diagnostic disable-next-line:no-unknown
|
||||
vim.o[option] = value
|
||||
else
|
||||
vim.api.nvim_create_autocmd('VimEnter', {
|
||||
group = group,
|
||||
nvim_on('VimEnter', group, {
|
||||
once = true,
|
||||
nested = true,
|
||||
callback = function()
|
||||
setoption(option, value, force)
|
||||
end,
|
||||
})
|
||||
}, function()
|
||||
setoption(option, value, force)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -950,22 +926,20 @@ do
|
||||
end
|
||||
end)
|
||||
|
||||
vim.api.nvim_create_autocmd('VimEnter', {
|
||||
group = group,
|
||||
nvim_on('VimEnter', group, {
|
||||
nested = true,
|
||||
once = true,
|
||||
callback = function()
|
||||
local optinfo = vim.api.nvim_get_option_info2('background', {})
|
||||
local sid_lua = -8
|
||||
if
|
||||
optinfo.was_set
|
||||
and optinfo.last_set_sid ~= sid_lua
|
||||
and next(vim.api.nvim_get_autocmds({ id = id })) ~= nil
|
||||
then
|
||||
vim.api.nvim_del_autocmd(id)
|
||||
end
|
||||
end,
|
||||
})
|
||||
}, function()
|
||||
local optinfo = vim.api.nvim_get_option_info2('background', {})
|
||||
local sid_lua = -8
|
||||
if
|
||||
optinfo.was_set
|
||||
and optinfo.last_set_sid ~= sid_lua
|
||||
and next(vim.api.nvim_get_autocmds({ id = id })) ~= nil
|
||||
then
|
||||
vim.api.nvim_del_autocmd(id)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Wait until detection of OSC 11 capabilities is complete to
|
||||
-- ensure background is automatically set before user config.
|
||||
@@ -1068,22 +1042,20 @@ do
|
||||
|
||||
if tty then
|
||||
-- Show progress bars in supporting terminals
|
||||
vim.api.nvim_create_autocmd('Progress', {
|
||||
group = vim.api.nvim_create_augroup('nvim.progress', {}),
|
||||
nvim_on('Progress', vim.api.nvim_create_augroup('nvim.progress', {}), {
|
||||
desc = 'Display native progress bars',
|
||||
callback = function(ev)
|
||||
if ev.data.status == 'running' then
|
||||
if ev.data.percent ~= nil then
|
||||
vim.api.nvim_ui_send(string.format('\027]9;4;1;%d\027\\', ev.data.percent))
|
||||
else
|
||||
-- "Indeterminate" progress (unknown percent).
|
||||
vim.api.nvim_ui_send(string.format('\027]9;4;3\027\\'))
|
||||
end
|
||||
}, function(ev)
|
||||
if ev.data.status == 'running' then
|
||||
if ev.data.percent ~= nil then
|
||||
vim.api.nvim_ui_send(string.format('\027]9;4;1;%d\027\\', ev.data.percent))
|
||||
else
|
||||
vim.api.nvim_ui_send('\027]9;4;0;0\027\\')
|
||||
-- "Indeterminate" progress (unknown percent).
|
||||
vim.api.nvim_ui_send(string.format('\027]9;4;3\027\\'))
|
||||
end
|
||||
end,
|
||||
})
|
||||
else
|
||||
vim.api.nvim_ui_send('\027]9;4;0;0\027\\')
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
--- - |g<| at any time.
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local M = {
|
||||
ns = api.nvim_create_namespace('nvim.ui2'),
|
||||
augroup = api.nvim_create_augroup('nvim.ui2', {}),
|
||||
@@ -229,30 +230,26 @@ function M.enable(opts)
|
||||
end)
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('OptionSet', {
|
||||
group = M.augroup,
|
||||
nvim_on('OptionSet', M.augroup, {
|
||||
pattern = { 'cmdheight', 'laststatus' },
|
||||
callback = function(ev)
|
||||
if ev.match == 'cmdheight' then
|
||||
check_cmdheight(vim.v.option_new)
|
||||
end
|
||||
M.msg.set_pos()
|
||||
end,
|
||||
desc = 'Set cmdline and message window dimensions for changed option values.',
|
||||
})
|
||||
}, function(ev)
|
||||
if ev.match == 'cmdheight' then
|
||||
check_cmdheight(vim.v.option_new)
|
||||
end
|
||||
M.msg.set_pos()
|
||||
end)
|
||||
|
||||
api.nvim_create_autocmd({ 'VimResized', 'TabEnter' }, {
|
||||
group = M.augroup,
|
||||
callback = function(ev)
|
||||
M.check_targets()
|
||||
-- After a tabpage was closed unhide the msg window on the current tabpage.
|
||||
if ev.event == 'TabEnter' and next(M.msg.msg.ids) ~= nil then
|
||||
api.nvim_win_set_config(M.wins.msg, { hide = false, width = M.msg.msg.width })
|
||||
end
|
||||
M.msg.set_pos()
|
||||
end,
|
||||
nvim_on({ 'VimResized', 'TabEnter' }, M.augroup, {
|
||||
desc = 'Set cmdline and message window dimensions after shell resize or tabpage change.',
|
||||
})
|
||||
}, function(ev)
|
||||
M.check_targets()
|
||||
-- After a tabpage was closed unhide the msg window on the current tabpage.
|
||||
if ev.event == 'TabEnter' and next(M.msg.msg.ids) ~= nil then
|
||||
api.nvim_win_set_config(M.wins.msg, { hide = false, width = M.msg.msg.width })
|
||||
end
|
||||
M.msg.set_pos()
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api, fn, o = vim.api, vim.fn, vim.o
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local ui = require('vim._core.ui2')
|
||||
|
||||
---@alias Msg { extid: integer, timer: uv.uv_timer_t? }
|
||||
@@ -634,35 +635,33 @@ local function enter_pager()
|
||||
local height, id = api.nvim_win_get_height(ui.wins.pager), 0
|
||||
api.nvim_set_option_value('eiw', '', { scope = 'local', win = ui.wins.pager })
|
||||
api.nvim_set_current_win(ui.wins.pager)
|
||||
id = api.nvim_create_autocmd({ 'WinEnter', 'CmdwinEnter', 'WinResized' }, {
|
||||
group = ui.augroup,
|
||||
callback = function(ev)
|
||||
if fn.getcmdtype() ~= '' then
|
||||
-- WinEnter fires before we can detect cmdwin will be entered: keep open.
|
||||
return
|
||||
elseif ev.event == 'WinResized' and fn.getcmdwintype() == '' then
|
||||
-- Remember height to be restored when cmdwin is closed.
|
||||
height = api.nvim_win_get_height(ui.wins.pager)
|
||||
elseif ev.event == 'WinEnter' then
|
||||
-- Close when no longer current window.
|
||||
in_pager = api.nvim_get_current_win() == ui.wins.pager
|
||||
end
|
||||
in_pager = in_pager and api.nvim_win_is_valid(ui.wins.pager)
|
||||
local cfg = in_pager and { relative = 'laststatus', col = 0 } or { hide = true }
|
||||
if in_pager then
|
||||
cfg.row, cfg.height, cfg.border = win_row_height_border('pager', height)
|
||||
else
|
||||
pcall(api.nvim_set_option_value, 'eiw', 'all', { scope = 'local', win = ui.wins.pager })
|
||||
api.nvim_del_autocmd(id)
|
||||
if was_cmdwin ~= '' then
|
||||
api.nvim_feedkeys('q' .. was_cmdwin, 'n', false)
|
||||
was_cmdwin = ''
|
||||
end
|
||||
end
|
||||
pcall(api.nvim_win_set_config, ui.wins.pager, cfg)
|
||||
end,
|
||||
id = nvim_on({ 'WinEnter', 'CmdwinEnter', 'WinResized' }, ui.augroup, {
|
||||
desc = 'Hide or reposition pager window.',
|
||||
})
|
||||
}, function(ev)
|
||||
if fn.getcmdtype() ~= '' then
|
||||
-- WinEnter fires before we can detect cmdwin will be entered: keep open.
|
||||
return
|
||||
elseif ev.event == 'WinResized' and fn.getcmdwintype() == '' then
|
||||
-- Remember height to be restored when cmdwin is closed.
|
||||
height = api.nvim_win_get_height(ui.wins.pager)
|
||||
elseif ev.event == 'WinEnter' then
|
||||
-- Close when no longer current window.
|
||||
in_pager = api.nvim_get_current_win() == ui.wins.pager
|
||||
end
|
||||
in_pager = in_pager and api.nvim_win_is_valid(ui.wins.pager)
|
||||
local cfg = in_pager and { relative = 'laststatus', col = 0 } or { hide = true }
|
||||
if in_pager then
|
||||
cfg.row, cfg.height, cfg.border = win_row_height_border('pager', height)
|
||||
else
|
||||
pcall(api.nvim_set_option_value, 'eiw', 'all', { scope = 'local', win = ui.wins.pager })
|
||||
api.nvim_del_autocmd(id)
|
||||
if was_cmdwin ~= '' then
|
||||
api.nvim_feedkeys('q' .. was_cmdwin, 'n', false)
|
||||
was_cmdwin = ''
|
||||
end
|
||||
end
|
||||
pcall(api.nvim_win_set_config, ui.wins.pager, cfg)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
@@ -172,4 +172,33 @@ function M.echo_err(msg)
|
||||
vim.api.nvim_echo({ { msg } }, true, { err = true })
|
||||
end
|
||||
|
||||
--- Define event-handlers (autocmds) ergonomically.
|
||||
---
|
||||
--- Examples:
|
||||
--- ```lua
|
||||
--- local nvim_on = require('vim._core.util').nvim_on
|
||||
--- nvim_on('BufWritePost', group, function(ev) print(ev.file) end)
|
||||
--- nvim_on({ 'BufRead', 'BufNew' }, group, { pattern = '*.lua' }, function(ev) end)
|
||||
--- nvim_on('VimLeavePre', nil, function() end)
|
||||
--- ```
|
||||
---
|
||||
--- @param events vim.api.keyset.events|vim.api.keyset.events[] Event(s) to watch. See |autocmd-events|.
|
||||
--- @param group string|integer? Group name or id, or `nil`.
|
||||
--- @param opts_or_fn vim.api.keyset.create_autocmd Options.
|
||||
--- @param fn fun(ev: vim.api.keyset.create_autocmd.callback_args): boolean? Event handler.
|
||||
--- @return integer # Autocmd id (see |nvim_create_autocmd()|).
|
||||
--- @overload fun(events: vim.api.keyset.events|vim.api.keyset.events[], group: string|integer?, fn: fun(ev: vim.api.keyset.create_autocmd.callback_args): boolean?): integer
|
||||
function M.nvim_on(events, group, opts_or_fn, fn)
|
||||
vim.validate('opts_or_fn', opts_or_fn, { 'function', 'table' })
|
||||
local opts --- @type vim.api.keyset.create_autocmd
|
||||
if type(opts_or_fn) == 'function' then
|
||||
fn, opts = opts_or_fn, {}
|
||||
else
|
||||
opts = opts_or_fn
|
||||
end
|
||||
opts.group = group
|
||||
opts.callback = fn
|
||||
return vim.api.nvim_create_autocmd(events, opts)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
-- TODO(lewis6991): deprecate some top level functions in favour of the submodule version
|
||||
-- e.g. vim.diagnostic.get_namespace() -> vim.diagnostic.namespace.get()
|
||||
@@ -1139,14 +1140,12 @@ function M.status(buf)
|
||||
return result_str
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('DiagnosticChanged', {
|
||||
group = api.nvim_create_augroup('nvim.diagnostic.status', {}),
|
||||
callback = function(ev)
|
||||
if api.nvim_buf_is_loaded(ev.buf) then
|
||||
api.nvim__redraw({ buf = ev.buf, statusline = true })
|
||||
end
|
||||
end,
|
||||
nvim_on('DiagnosticChanged', api.nvim_create_augroup('nvim.diagnostic.status', {}), {
|
||||
desc = 'diagnostics component for the statusline',
|
||||
})
|
||||
}, function(ev)
|
||||
if api.nvim_buf_is_loaded(ev.buf) then
|
||||
api.nvim__redraw({ buf = ev.buf, statusline = true })
|
||||
end
|
||||
end)
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local diagnostic_modules = vim._defer_require('vim.diagnostic', {
|
||||
_config = ..., --- @module 'vim.diagnostic._config'
|
||||
@@ -62,14 +63,12 @@ local function schedule_display(namespace, bufnr, args)
|
||||
local key = make_augroup_key(namespace, bufnr)
|
||||
if not registered_autocmds[key] then
|
||||
local group = api.nvim_create_augroup(key, { clear = true })
|
||||
api.nvim_create_autocmd(insert_leave_auto_cmds, {
|
||||
group = group,
|
||||
nvim_on(insert_leave_auto_cmds, group, {
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
execute_scheduled_display(namespace, bufnr)
|
||||
end,
|
||||
desc = 'vim.diagnostic: display diagnostics',
|
||||
})
|
||||
}, function()
|
||||
execute_scheduled_display(namespace, bufnr)
|
||||
end)
|
||||
registered_autocmds[key] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local diagnostic = vim.diagnostic
|
||||
local diagnostic_shared = require('vim.diagnostic._shared')
|
||||
|
||||
@@ -123,13 +124,9 @@ local function once_buf_loaded(bufnr, fn)
|
||||
if api.nvim_buf_is_loaded(bufnr) then
|
||||
fn()
|
||||
else
|
||||
return api.nvim_create_autocmd('BufRead', {
|
||||
buf = bufnr,
|
||||
once = true,
|
||||
callback = function()
|
||||
fn()
|
||||
end,
|
||||
})
|
||||
return nvim_on('BufRead', nil, { buf = bufnr, once = true }, function()
|
||||
fn()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -436,13 +433,9 @@ function M.virtual_text.show(namespace, bufnr, diagnostics, opts)
|
||||
local line_diagnostics = diagnostic_shared.diagnostic_lines(diagnostics, true)
|
||||
|
||||
if vopts.current_line ~= nil then
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
buf = bufnr,
|
||||
group = ns.user_data.virt_text_augroup,
|
||||
callback = function()
|
||||
render_virtual_text(ns.user_data.virt_text_ns, bufnr, line_diagnostics, vopts)
|
||||
end,
|
||||
})
|
||||
nvim_on('CursorMoved', ns.user_data.virt_text_augroup, { buf = bufnr }, function()
|
||||
render_virtual_text(ns.user_data.virt_text_ns, bufnr, line_diagnostics, vopts)
|
||||
end)
|
||||
end
|
||||
|
||||
render_virtual_text(ns.user_data.virt_text_ns, bufnr, line_diagnostics, vopts)
|
||||
@@ -690,17 +683,13 @@ function M.virtual_lines.show(namespace, bufnr, diagnostics, opts)
|
||||
-- Create a mapping from line -> diagnostics so that we can quickly get the
|
||||
-- diagnostics we need when the cursor line doesn't change.
|
||||
local line_diagnostics = diagnostic_shared.diagnostic_lines(diagnostics, true)
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
buf = bufnr,
|
||||
group = ns.user_data.virt_lines_augroup,
|
||||
callback = function()
|
||||
render_virtual_lines(
|
||||
ns.user_data.virt_lines_ns,
|
||||
bufnr,
|
||||
diagnostic_shared.diagnostics_at_cursor(line_diagnostics)
|
||||
)
|
||||
end,
|
||||
})
|
||||
nvim_on('CursorMoved', ns.user_data.virt_lines_augroup, { buf = bufnr }, function()
|
||||
render_virtual_lines(
|
||||
ns.user_data.virt_lines_ns,
|
||||
bufnr,
|
||||
diagnostic_shared.diagnostics_at_cursor(line_diagnostics)
|
||||
)
|
||||
end)
|
||||
|
||||
-- Also show diagnostics for the current line before the first CursorMoved event.
|
||||
render_virtual_lines(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local severity_module = require('vim.diagnostic._severity')
|
||||
|
||||
@@ -14,13 +15,9 @@ setmetatable(diagnostic_cache, {
|
||||
--- @param bufnr integer
|
||||
__index = function(t, bufnr)
|
||||
assert(bufnr > 0, 'Invalid buffer number')
|
||||
api.nvim_create_autocmd('BufWipeout', {
|
||||
group = group,
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
rawset(t, bufnr, nil)
|
||||
end,
|
||||
})
|
||||
nvim_on('BufWipeout', group, { buf = bufnr }, function()
|
||||
rawset(t, bufnr, nil)
|
||||
end)
|
||||
t[bufnr] = {}
|
||||
return t[bufnr]
|
||||
end,
|
||||
@@ -50,13 +47,12 @@ local function once_buf_loaded(bufnr, fn)
|
||||
if api.nvim_buf_is_loaded(bufnr) then
|
||||
fn()
|
||||
else
|
||||
return api.nvim_create_autocmd('BufRead', {
|
||||
return nvim_on('BufRead', nil, {
|
||||
buf = bufnr,
|
||||
once = true,
|
||||
callback = function()
|
||||
fn()
|
||||
end,
|
||||
})
|
||||
}, function()
|
||||
fn()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local M = {}
|
||||
local health = require('vim.health')
|
||||
|
||||
@@ -707,31 +709,27 @@ local function check_sysinfo()
|
||||
)
|
||||
)
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'checkhealth',
|
||||
once = true,
|
||||
callback = function(ev)
|
||||
local buf = ev.buf
|
||||
local win = vim.fn.bufwinid(buf)
|
||||
if win == -1 then
|
||||
return
|
||||
end
|
||||
local encoded_body = vim.uri_encode(body) --- @type string
|
||||
local issue_url = 'https://github.com/neovim/neovim/issues/new?type=Bug&body=' .. encoded_body
|
||||
nvim_on('FileType', nil, { pattern = 'checkhealth', once = true }, function(ev)
|
||||
local buf = ev.buf
|
||||
local win = vim.fn.bufwinid(buf)
|
||||
if win == -1 then
|
||||
return
|
||||
end
|
||||
local encoded_body = vim.uri_encode(body) --- @type string
|
||||
local issue_url = 'https://github.com/neovim/neovim/issues/new?type=Bug&body=' .. encoded_body
|
||||
|
||||
_G.nvim_health_bugreport_open = function()
|
||||
vim.ui.open(issue_url)
|
||||
end
|
||||
vim.wo[win].winbar =
|
||||
'%#WarningMsg#%@v:lua.nvim_health_bugreport_open@▶ Create Bug Report on GitHub%X%*'
|
||||
_G.nvim_health_bugreport_open = function()
|
||||
vim.ui.open(issue_url)
|
||||
end
|
||||
vim.wo[win].winbar =
|
||||
'%#WarningMsg#%@v:lua.nvim_health_bugreport_open@▶ Create Bug Report on GitHub%X%*'
|
||||
|
||||
vim.api.nvim_create_autocmd('BufDelete', {
|
||||
buf = buf,
|
||||
once = true,
|
||||
command = 'lua _G.nvim_health_bugreport_open = nil',
|
||||
})
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd('BufDelete', {
|
||||
buf = buf,
|
||||
once = true,
|
||||
command = 'lua _G.nvim_health_bugreport_open = nil',
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
function M.check()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local api = vim.api
|
||||
local validate = vim.validate
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local lsp = vim._defer_require('vim.lsp', {
|
||||
_capability = ..., --- @module 'vim.lsp._capability'
|
||||
@@ -643,12 +644,9 @@ function lsp.enable(name, enable)
|
||||
else
|
||||
-- Only ever create autocmd once to reuse computation of config merging.
|
||||
lsp_enable_autocmd_id = lsp_enable_autocmd_id
|
||||
or api.nvim_create_autocmd('FileType', {
|
||||
group = api.nvim_create_augroup('nvim.lsp.enable', {}),
|
||||
callback = function(ev)
|
||||
lsp_enable_callback(ev.buf)
|
||||
end,
|
||||
})
|
||||
or nvim_on('FileType', api.nvim_create_augroup('nvim.lsp.enable', {}), function(ev)
|
||||
lsp_enable_callback(ev.buf)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Ensure any pre-existing buffers start/stop their LSP clients.
|
||||
@@ -909,41 +907,37 @@ local function buf_attach(bufnr)
|
||||
local uri = vim.uri_from_bufnr(bufnr)
|
||||
local augroup = ('nvim.lsp.b_%d_save'):format(bufnr)
|
||||
local group = api.nvim_create_augroup(augroup, { clear = true })
|
||||
api.nvim_create_autocmd('BufWritePre', {
|
||||
group = group,
|
||||
nvim_on('BufWritePre', group, {
|
||||
buf = bufnr,
|
||||
desc = 'vim.lsp: textDocument/willSave',
|
||||
callback = function(ctx)
|
||||
for _, client in ipairs(lsp.get_clients({ bufnr = ctx.buf })) do
|
||||
local params = {
|
||||
textDocument = {
|
||||
uri = uri,
|
||||
},
|
||||
reason = protocol.TextDocumentSaveReason.Manual, ---@type integer
|
||||
}
|
||||
if client:supports_method('textDocument/willSave') then
|
||||
client:notify('textDocument/willSave', params)
|
||||
end
|
||||
if client:supports_method('textDocument/willSaveWaitUntil') then
|
||||
local result, err =
|
||||
client:request_sync('textDocument/willSaveWaitUntil', params, 1000, ctx.buf)
|
||||
if result and result.result then
|
||||
util.apply_text_edits(result.result, ctx.buf, client.offset_encoding)
|
||||
elseif err then
|
||||
log.error(vim.inspect(err))
|
||||
end
|
||||
}, function(ctx)
|
||||
for _, client in ipairs(lsp.get_clients({ bufnr = ctx.buf })) do
|
||||
local params = {
|
||||
textDocument = {
|
||||
uri = uri,
|
||||
},
|
||||
reason = protocol.TextDocumentSaveReason.Manual, ---@type integer
|
||||
}
|
||||
if client:supports_method('textDocument/willSave') then
|
||||
client:notify('textDocument/willSave', params)
|
||||
end
|
||||
if client:supports_method('textDocument/willSaveWaitUntil') then
|
||||
local result, err =
|
||||
client:request_sync('textDocument/willSaveWaitUntil', params, 1000, ctx.buf)
|
||||
if result and result.result then
|
||||
util.apply_text_edits(result.result, ctx.buf, client.offset_encoding)
|
||||
elseif err then
|
||||
log.error(vim.inspect(err))
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('BufWritePost', {
|
||||
group = group,
|
||||
end
|
||||
end)
|
||||
nvim_on('BufWritePost', group, {
|
||||
buf = bufnr,
|
||||
desc = 'vim.lsp: textDocument/didSave handler',
|
||||
callback = function(ctx)
|
||||
text_document_did_save_handler(ctx.buf)
|
||||
end,
|
||||
})
|
||||
}, function(ctx)
|
||||
text_document_did_save_handler(ctx.buf)
|
||||
end)
|
||||
-- First time, so attach and set up stuff.
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_lines = function(_, _, changedtick, firstline, lastline, new_lastline)
|
||||
@@ -1169,42 +1163,36 @@ end
|
||||
-- Minimum time before warning about LSP exit_timeout on Nvim exit.
|
||||
local min_warn_exit_timeout = 100
|
||||
|
||||
api.nvim_create_autocmd('VimLeavePre', {
|
||||
desc = 'vim.lsp: exit handler',
|
||||
callback = function()
|
||||
local active_clients = lsp.get_clients()
|
||||
log.info('exit_handler', active_clients)
|
||||
nvim_on('VimLeavePre', nil, { desc = 'vim.lsp: exit handler' }, function()
|
||||
local active_clients = lsp.get_clients()
|
||||
log.info('exit_handler', active_clients)
|
||||
|
||||
local max_timeout = 0
|
||||
for _, client in pairs(active_clients) do
|
||||
max_timeout = math.max(max_timeout, vim._tointeger(client.exit_timeout) or 0)
|
||||
client:stop(client.exit_timeout)
|
||||
end
|
||||
local max_timeout = 0
|
||||
for _, client in pairs(active_clients) do
|
||||
max_timeout = math.max(max_timeout, vim._tointeger(client.exit_timeout) or 0)
|
||||
client:stop(client.exit_timeout)
|
||||
end
|
||||
|
||||
local exit_warning_timer = max_timeout > min_warn_exit_timeout
|
||||
and vim.defer_fn(function()
|
||||
api.nvim_echo({
|
||||
{
|
||||
string.format(
|
||||
'Waiting %ss for LSP exit (Press Ctrl-C to force exit)',
|
||||
max_timeout / 1e3
|
||||
),
|
||||
'WarningMsg',
|
||||
},
|
||||
}, true, {})
|
||||
end, min_warn_exit_timeout)
|
||||
local exit_warning_timer = max_timeout > min_warn_exit_timeout
|
||||
and vim.defer_fn(function()
|
||||
api.nvim_echo({
|
||||
{
|
||||
string.format('Waiting %ss for LSP exit (Press Ctrl-C to force exit)', max_timeout / 1e3),
|
||||
'WarningMsg',
|
||||
},
|
||||
}, true, {})
|
||||
end, min_warn_exit_timeout)
|
||||
|
||||
vim.wait(max_timeout, function()
|
||||
return vim.iter(active_clients):all(function(client)
|
||||
return client.rpc.is_closing()
|
||||
end)
|
||||
vim.wait(max_timeout, function()
|
||||
return vim.iter(active_clients):all(function(client)
|
||||
return client.rpc.is_closing()
|
||||
end)
|
||||
end)
|
||||
|
||||
if exit_warning_timer and not exit_warning_timer:is_closing() then
|
||||
exit_warning_timer:close()
|
||||
end
|
||||
end,
|
||||
})
|
||||
if exit_warning_timer and not exit_warning_timer:is_closing() then
|
||||
exit_warning_timer:close()
|
||||
end
|
||||
end)
|
||||
|
||||
---@nodoc
|
||||
--- Sends an async request for all active clients attached to the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local util = require('vim.lsp.util')
|
||||
local log = require('vim.lsp.log')
|
||||
local tableclear = require('vim._core.table').clear
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local api = vim.api
|
||||
|
||||
---@type table<lsp.FoldingRangeKind, true>
|
||||
@@ -116,14 +117,10 @@ local scheduled_foldupdate = {}
|
||||
local function schedule_foldupdate(bufnr)
|
||||
if not scheduled_foldupdate[bufnr] then
|
||||
scheduled_foldupdate[bufnr] = true
|
||||
api.nvim_create_autocmd('InsertLeave', {
|
||||
buf = bufnr,
|
||||
once = true,
|
||||
callback = function()
|
||||
foldupdate(bufnr)
|
||||
scheduled_foldupdate[bufnr] = nil
|
||||
end,
|
||||
})
|
||||
nvim_on('InsertLeave', nil, { buf = bufnr, once = true }, function()
|
||||
foldupdate(bufnr)
|
||||
scheduled_foldupdate[bufnr] = nil
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,35 +235,23 @@ function State:new(bufnr)
|
||||
end
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('LspNotify', {
|
||||
group = self.augroup,
|
||||
buf = bufnr,
|
||||
callback = function(ev)
|
||||
local client = assert(vim.lsp.get_client_by_id(ev.data.client_id))
|
||||
if
|
||||
client:supports_method('textDocument/foldingRange', bufnr)
|
||||
and (ev.data.method == 'textDocument/didChange' or ev.data.method == 'textDocument/didOpen')
|
||||
then
|
||||
self:refresh(client)
|
||||
end
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('OptionSet', {
|
||||
group = self.augroup,
|
||||
pattern = 'foldexpr',
|
||||
callback = function()
|
||||
if vim.v.option_type == 'global' or api.nvim_get_current_buf() == bufnr then
|
||||
vim.lsp._capability.enable('folding_range', false, { bufnr = bufnr })
|
||||
end
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('FileType', {
|
||||
group = self.augroup,
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
self:reset()
|
||||
end,
|
||||
})
|
||||
nvim_on('LspNotify', self.augroup, { buf = bufnr }, function(ev)
|
||||
local client = assert(vim.lsp.get_client_by_id(ev.data.client_id))
|
||||
if
|
||||
client:supports_method('textDocument/foldingRange', bufnr)
|
||||
and (ev.data.method == 'textDocument/didChange' or ev.data.method == 'textDocument/didOpen')
|
||||
then
|
||||
self:refresh(client)
|
||||
end
|
||||
end)
|
||||
nvim_on('OptionSet', self.augroup, { pattern = 'foldexpr' }, function()
|
||||
if vim.v.option_type == 'global' or api.nvim_get_current_buf() == bufnr then
|
||||
vim.lsp._capability.enable('folding_range', false, { bufnr = bufnr })
|
||||
end
|
||||
end)
|
||||
nvim_on('FileType', self.augroup, { buf = bufnr }, function()
|
||||
self:reset()
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
--- The `vim.lsp.buf_…` functions perform operations for LSP clients attached to the current buffer.
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local lsp = vim.lsp
|
||||
local validate = vim.validate
|
||||
local util = require('vim.lsp.util')
|
||||
@@ -188,14 +189,10 @@ function M.hover(config)
|
||||
|
||||
local _, winid = lsp.util.open_floating_preview(contents, format, config)
|
||||
|
||||
api.nvim_create_autocmd('WinClosed', {
|
||||
pattern = tostring(winid),
|
||||
once = true,
|
||||
callback = function()
|
||||
api.nvim_buf_clear_namespace(bufnr, hover_ns, 0, -1)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
nvim_on('WinClosed', nil, { pattern = tostring(winid), once = true }, function()
|
||||
api.nvim_buf_clear_namespace(bufnr, hover_ns, 0, -1)
|
||||
return true
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -1509,13 +1506,9 @@ function M.selection_range(direction, timeout_ms)
|
||||
end
|
||||
|
||||
-- Clear selection ranges when leaving visual mode.
|
||||
api.nvim_create_autocmd('ModeChanged', {
|
||||
once = true,
|
||||
pattern = 'v*:*',
|
||||
callback = function()
|
||||
selection_ranges = nil
|
||||
end,
|
||||
})
|
||||
nvim_on('ModeChanged', nil, { once = true, pattern = 'v*:*' }, function()
|
||||
selection_ranges = nil
|
||||
end)
|
||||
|
||||
if #ranges > 0 then
|
||||
local index = math.min(#ranges, math.max(1, direction))
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
local M = {}
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local lsp = vim.lsp
|
||||
local protocol = lsp.protocol
|
||||
|
||||
@@ -789,55 +790,53 @@ end
|
||||
--- Defines a CompleteChanged handler to request and display LSP completion item documentation
|
||||
--- via completionItem/resolve
|
||||
local function on_completechanged(group, bufnr)
|
||||
api.nvim_create_autocmd('CompleteChanged', {
|
||||
group = group,
|
||||
nvim_on('CompleteChanged', group, {
|
||||
buf = bufnr,
|
||||
callback = function(ev)
|
||||
local completed_item = vim.v.event.completed_item or {}
|
||||
local lsp_item = vim.tbl_get(completed_item, 'user_data', 'nvim', 'lsp', 'completion_item')
|
||||
local data = vim.fn.complete_info({ 'selected' })
|
||||
if (completed_item.info or '') ~= '' then
|
||||
local kind = vim.tbl_get(lsp_item or {}, 'documentation', 'kind')
|
||||
update_popup_window(
|
||||
data.preview_winid,
|
||||
data.preview_bufnr,
|
||||
kind or protocol.MarkupKind.Markdown
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if
|
||||
#lsp.get_clients({
|
||||
id = vim.tbl_get(completed_item, 'user_data', 'nvim', 'lsp', 'client_id'),
|
||||
method = 'completionItem/resolve',
|
||||
bufnr = ev.buf,
|
||||
}) == 0
|
||||
then
|
||||
if
|
||||
has_completeopt('popup')
|
||||
and lsp_item
|
||||
and lsp_item.insertTextFormat == protocol.InsertTextFormat.Snippet
|
||||
then
|
||||
-- Shows snippet preview in doc popup if completeopt=popup.
|
||||
local text = parse_snippet(lsp_item.insertText or lsp_item.textEdit.newText)
|
||||
local windata = api.nvim__complete_set(
|
||||
data.selected,
|
||||
{ info = ('```%s\n%s\n```'):format(vim.bo.filetype, text) }
|
||||
)
|
||||
update_popup_window(windata.winid, windata.bufnr, protocol.MarkupKind.Markdown)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Retrieve the raw LSP completionItem from completed_item as the parameter for
|
||||
-- the completionItem/resolve request
|
||||
if lsp_item then
|
||||
Context.resolve_handler = Context.resolve_handler or CompletionResolver.new()
|
||||
Context.resolve_handler:request(ev.buf, lsp_item, completed_item.word)
|
||||
end
|
||||
end,
|
||||
desc = 'Request and display LSP completion item documentation via completionItem/resolve',
|
||||
})
|
||||
}, function(ev)
|
||||
local completed_item = vim.v.event.completed_item or {}
|
||||
local lsp_item = vim.tbl_get(completed_item, 'user_data', 'nvim', 'lsp', 'completion_item')
|
||||
local data = vim.fn.complete_info({ 'selected' })
|
||||
if (completed_item.info or '') ~= '' then
|
||||
local kind = vim.tbl_get(lsp_item or {}, 'documentation', 'kind')
|
||||
update_popup_window(
|
||||
data.preview_winid,
|
||||
data.preview_bufnr,
|
||||
kind or protocol.MarkupKind.Markdown
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if
|
||||
#lsp.get_clients({
|
||||
id = vim.tbl_get(completed_item, 'user_data', 'nvim', 'lsp', 'client_id'),
|
||||
method = 'completionItem/resolve',
|
||||
bufnr = ev.buf,
|
||||
}) == 0
|
||||
then
|
||||
if
|
||||
has_completeopt('popup')
|
||||
and lsp_item
|
||||
and lsp_item.insertTextFormat == protocol.InsertTextFormat.Snippet
|
||||
then
|
||||
-- Shows snippet preview in doc popup if completeopt=popup.
|
||||
local text = parse_snippet(lsp_item.insertText or lsp_item.textEdit.newText)
|
||||
local windata = api.nvim__complete_set(
|
||||
data.selected,
|
||||
{ info = ('```%s\n%s\n```'):format(vim.bo.filetype, text) }
|
||||
)
|
||||
update_popup_window(windata.winid, windata.bufnr, protocol.MarkupKind.Markdown)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Retrieve the raw LSP completionItem from completed_item as the parameter for
|
||||
-- the completionItem/resolve request
|
||||
if lsp_item then
|
||||
Context.resolve_handler = Context.resolve_handler or CompletionResolver.new()
|
||||
Context.resolve_handler:request(ev.buf, lsp_item, completed_item.word)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function on_complete_done()
|
||||
@@ -941,16 +940,12 @@ local function register_completedone(bufnr)
|
||||
return group
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('CompleteDone', {
|
||||
group = group,
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
local reason = api.nvim_get_vvar('event').reason ---@type string
|
||||
if reason == 'accept' then
|
||||
on_complete_done()
|
||||
end
|
||||
end,
|
||||
})
|
||||
nvim_on('CompleteDone', group, { buf = bufnr }, function()
|
||||
local reason = api.nvim_get_vvar('event').reason ---@type string
|
||||
if reason == 'accept' then
|
||||
on_complete_done()
|
||||
end
|
||||
end)
|
||||
|
||||
return group
|
||||
end
|
||||
@@ -1167,28 +1162,18 @@ local function enable_completions(client_id, bufnr, opts)
|
||||
|
||||
-- Set up autocommands.
|
||||
local group = register_completedone(bufnr)
|
||||
api.nvim_create_autocmd('LspDetach', {
|
||||
group = group,
|
||||
nvim_on('LspDetach', group, {
|
||||
buf = bufnr,
|
||||
desc = 'vim.lsp.completion: clean up client on detach',
|
||||
callback = function(ev)
|
||||
disable_completions(ev.data.client_id, ev.buf)
|
||||
end,
|
||||
})
|
||||
}, function(ev)
|
||||
disable_completions(ev.data.client_id, ev.buf)
|
||||
end)
|
||||
|
||||
if opts.autotrigger then
|
||||
api.nvim_create_autocmd('InsertCharPre', {
|
||||
group = group,
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
on_insert_char_pre(buf_handles[bufnr])
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('InsertLeave', {
|
||||
group = group,
|
||||
buf = bufnr,
|
||||
callback = on_insert_leave,
|
||||
})
|
||||
nvim_on('InsertCharPre', group, { buf = bufnr }, function()
|
||||
on_insert_char_pre(buf_handles[bufnr])
|
||||
end)
|
||||
nvim_on('InsertLeave', group, { buf = bufnr }, on_insert_leave)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ local protocol = lsp.protocol
|
||||
local util = lsp.util
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -416,22 +417,18 @@ function M._enable(bufnr)
|
||||
bufstates[bufnr] = { pull_kind = 'document', client_result_id = {} }
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('LspNotify', {
|
||||
buf = bufnr,
|
||||
callback = function(opts)
|
||||
if
|
||||
opts.data.method ~= 'textDocument/didChange'
|
||||
and opts.data.method ~= 'textDocument/didOpen'
|
||||
then
|
||||
return
|
||||
end
|
||||
if bufstates[bufnr] and bufstates[bufnr].pull_kind == 'document' then
|
||||
local client_id = opts.data.client_id --- @type integer?
|
||||
M._refresh(bufnr, client_id, true)
|
||||
end
|
||||
end,
|
||||
group = augroup,
|
||||
})
|
||||
nvim_on('LspNotify', augroup, { buf = bufnr }, function(opts)
|
||||
if
|
||||
opts.data.method ~= 'textDocument/didChange'
|
||||
and opts.data.method ~= 'textDocument/didOpen'
|
||||
then
|
||||
return
|
||||
end
|
||||
if bufstates[bufnr] and bufstates[bufnr].pull_kind == 'document' then
|
||||
local client_id = opts.data.client_id --- @type integer?
|
||||
M._refresh(bufnr, client_id, true)
|
||||
end
|
||||
end)
|
||||
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_reload = function()
|
||||
@@ -444,21 +441,15 @@ function M._enable(bufnr)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('LspDetach', {
|
||||
buf = bufnr,
|
||||
callback = function(ev)
|
||||
local clients = lsp.get_clients({ bufnr = bufnr, method = 'textDocument/diagnostic' })
|
||||
nvim_on('LspDetach', augroup, { buf = bufnr }, function(ev)
|
||||
local clients = lsp.get_clients({ bufnr = bufnr, method = 'textDocument/diagnostic' })
|
||||
|
||||
if
|
||||
not vim.iter(clients):any(function(c)
|
||||
return c.id ~= ev.data.client_id
|
||||
end)
|
||||
then
|
||||
disable(bufnr)
|
||||
end
|
||||
end,
|
||||
group = augroup,
|
||||
})
|
||||
if not vim.iter(clients):any(function(c)
|
||||
return c.id ~= ev.data.client_id
|
||||
end) then
|
||||
disable(bufnr)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Returns the result IDs from the reports provided by the given client.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
--- Highlighting is enabled by default.
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local lsp = vim.lsp
|
||||
local util = lsp.util
|
||||
local Capability = require('vim.lsp._capability')
|
||||
@@ -144,19 +145,15 @@ function Provider:new(bufnr)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('ColorScheme', {
|
||||
group = self.augroup,
|
||||
desc = 'Refresh document_color',
|
||||
callback = function()
|
||||
color_cache = {}
|
||||
n_color_cache = 0
|
||||
local provider = Provider.active[bufnr]
|
||||
if provider then
|
||||
provider:clear()
|
||||
provider:request()
|
||||
end
|
||||
end,
|
||||
})
|
||||
nvim_on('ColorScheme', self.augroup, { desc = 'Refresh document_color' }, function()
|
||||
color_cache = {}
|
||||
n_color_cache = 0
|
||||
local provider = Provider.active[bufnr]
|
||||
if provider then
|
||||
provider:clear()
|
||||
provider:request()
|
||||
end
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local util = require('vim.lsp.util')
|
||||
local log = require('vim.lsp.log')
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local api = vim.api
|
||||
local M = {}
|
||||
|
||||
@@ -263,55 +264,46 @@ local function _enable(bufnr)
|
||||
refresh(bufnr)
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('LspNotify', {
|
||||
callback = function(ev)
|
||||
---@type integer
|
||||
local bufnr = ev.buf
|
||||
nvim_on('LspNotify', augroup, function(ev)
|
||||
---@type integer
|
||||
local bufnr = ev.buf
|
||||
|
||||
if ev.data.method ~= 'textDocument/didChange' and ev.data.method ~= 'textDocument/didOpen' then
|
||||
return
|
||||
end
|
||||
if bufstates[bufnr].enabled then
|
||||
refresh(bufnr, ev.data.client_id)
|
||||
end
|
||||
end,
|
||||
group = augroup,
|
||||
})
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(ev)
|
||||
---@type integer
|
||||
local bufnr = ev.buf
|
||||
if ev.data.method ~= 'textDocument/didChange' and ev.data.method ~= 'textDocument/didOpen' then
|
||||
return
|
||||
end
|
||||
if bufstates[bufnr].enabled then
|
||||
refresh(bufnr, ev.data.client_id)
|
||||
end
|
||||
end)
|
||||
nvim_on('LspAttach', augroup, function(ev)
|
||||
---@type integer
|
||||
local bufnr = ev.buf
|
||||
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_reload = function(_, cb_bufnr)
|
||||
clear(cb_bufnr)
|
||||
if bufstates[cb_bufnr] and bufstates[cb_bufnr].enabled then
|
||||
bufstates[cb_bufnr].applied = {}
|
||||
refresh(cb_bufnr)
|
||||
end
|
||||
end,
|
||||
on_detach = function(_, cb_bufnr)
|
||||
_disable(cb_bufnr)
|
||||
bufstates[cb_bufnr] = nil
|
||||
end,
|
||||
})
|
||||
end,
|
||||
group = augroup,
|
||||
})
|
||||
api.nvim_create_autocmd('LspDetach', {
|
||||
callback = function(ev)
|
||||
---@type integer
|
||||
local bufnr = ev.buf
|
||||
local clients = vim.lsp.get_clients({ bufnr = bufnr, method = 'textDocument/inlayHint' })
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_reload = function(_, cb_bufnr)
|
||||
clear(cb_bufnr)
|
||||
if bufstates[cb_bufnr] and bufstates[cb_bufnr].enabled then
|
||||
bufstates[cb_bufnr].applied = {}
|
||||
refresh(cb_bufnr)
|
||||
end
|
||||
end,
|
||||
on_detach = function(_, cb_bufnr)
|
||||
_disable(cb_bufnr)
|
||||
bufstates[cb_bufnr] = nil
|
||||
end,
|
||||
})
|
||||
end)
|
||||
nvim_on('LspDetach', augroup, function(ev)
|
||||
---@type integer
|
||||
local bufnr = ev.buf
|
||||
local clients = vim.lsp.get_clients({ bufnr = bufnr, method = 'textDocument/inlayHint' })
|
||||
|
||||
if not vim.iter(clients):any(function(c)
|
||||
return c.id ~= ev.data.client_id
|
||||
end) then
|
||||
_disable(bufnr)
|
||||
end
|
||||
end,
|
||||
group = augroup,
|
||||
})
|
||||
if not vim.iter(clients):any(function(c)
|
||||
return c.id ~= ev.data.client_id
|
||||
end) then
|
||||
_disable(bufnr)
|
||||
end
|
||||
end)
|
||||
api.nvim_set_decoration_provider(namespace, {
|
||||
on_win = function(_, _, bufnr, topline, botline)
|
||||
---@type vim.lsp.inlay_hint.bufstate
|
||||
|
||||
@@ -40,6 +40,7 @@ local log = require('vim.lsp.log')
|
||||
local protocol = require('vim.lsp.protocol')
|
||||
local grammar = require('vim.lsp._snippet_grammar')
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local Capability = require('vim.lsp._capability')
|
||||
|
||||
@@ -78,20 +79,12 @@ Capability.all[Completor.name] = Completor
|
||||
function Completor:new(buf)
|
||||
self = Capability.new(self, buf)
|
||||
self.client_state = {}
|
||||
api.nvim_create_autocmd({ 'InsertEnter', 'CursorMovedI', 'TextChangedP' }, {
|
||||
group = self.augroup,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
self:automatic_request()
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd({ 'InsertLeave' }, {
|
||||
group = self.augroup,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
self:abort()
|
||||
end,
|
||||
})
|
||||
nvim_on({ 'InsertEnter', 'CursorMovedI', 'TextChangedP' }, self.augroup, { buf = buf }, function()
|
||||
self:automatic_request()
|
||||
end)
|
||||
nvim_on({ 'InsertLeave' }, self.augroup, { buf = buf }, function()
|
||||
self:abort()
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
local util = require('vim.lsp.util')
|
||||
local log = require('vim.lsp.log')
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local lsp = vim.lsp
|
||||
local method = 'textDocument/linkedEditingRange'
|
||||
local Range = require('vim.treesitter._range')
|
||||
@@ -201,30 +202,18 @@ function LinkedEditor.new(buf)
|
||||
self.augroup = augroup
|
||||
self.client_states = {}
|
||||
|
||||
api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, {
|
||||
buf = buf,
|
||||
group = augroup,
|
||||
callback = function()
|
||||
for _, client_state in pairs(self.client_states) do
|
||||
update_ranges(buf, client_state)
|
||||
end
|
||||
self:refresh()
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
group = augroup,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
self:refresh()
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('LspDetach', {
|
||||
group = augroup,
|
||||
buf = buf,
|
||||
callback = function(ev)
|
||||
self:detach(ev.data.client_id)
|
||||
end,
|
||||
})
|
||||
nvim_on({ 'TextChanged', 'TextChangedI' }, augroup, { buf = buf }, function()
|
||||
for _, client_state in pairs(self.client_states) do
|
||||
update_ranges(buf, client_state)
|
||||
end
|
||||
self:refresh()
|
||||
end)
|
||||
nvim_on('CursorMoved', augroup, { buf = buf }, function()
|
||||
self:refresh()
|
||||
end)
|
||||
nvim_on('LspDetach', augroup, { buf = buf }, function(ev)
|
||||
self:detach(ev.data.client_id)
|
||||
end)
|
||||
|
||||
LinkedEditor.active[buf] = self
|
||||
return self
|
||||
@@ -263,20 +252,19 @@ local function detach_linked_editor(bufnr, client)
|
||||
linked_editor:detach(client.id)
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
nvim_on('LspAttach', nil, {
|
||||
desc = 'Enable linked editing ranges for all buffers this client attaches to, if enabled',
|
||||
callback = function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if
|
||||
not client._enabled_capabilities['linked_editing_range']
|
||||
or not client:supports_method(method, ev.buf)
|
||||
then
|
||||
return
|
||||
end
|
||||
}, function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if
|
||||
not client._enabled_capabilities['linked_editing_range']
|
||||
or not client:supports_method(method, ev.buf)
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
attach_linked_editor(ev.buf, client)
|
||||
end,
|
||||
})
|
||||
attach_linked_editor(ev.buf, client)
|
||||
end)
|
||||
|
||||
---@param enable boolean
|
||||
---@param client vim.lsp.Client
|
||||
@@ -302,16 +290,14 @@ local function toggle_linked_editing_globally(enable)
|
||||
-- If disabling, only clear the attachment autocmd. If enabling, create it.
|
||||
local group = api.nvim_create_augroup('nvim.lsp.linked_editing_range', { clear = true })
|
||||
if enable then
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
group = group,
|
||||
nvim_on('LspAttach', group, {
|
||||
desc = 'Enable linked editing ranges for all clients',
|
||||
callback = function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client:supports_method(method, ev.buf) then
|
||||
attach_linked_editor(ev.buf, client)
|
||||
end
|
||||
end,
|
||||
})
|
||||
}, function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client:supports_method(method, ev.buf) then
|
||||
attach_linked_editor(ev.buf, client)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local lsp = vim.lsp
|
||||
local util = lsp.util
|
||||
local method = 'textDocument/onTypeFormatting'
|
||||
@@ -157,27 +158,24 @@ local function attach(client, bufnr)
|
||||
end
|
||||
|
||||
api.nvim_clear_autocmds({ group = augroup, buf = bufnr })
|
||||
api.nvim_create_autocmd('LspDetach', {
|
||||
nvim_on('LspDetach', augroup, {
|
||||
buf = bufnr,
|
||||
desc = 'Detach on-type formatting module when the client detaches',
|
||||
group = augroup,
|
||||
callback = function(ev)
|
||||
local detached_client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
detach(detached_client, bufnr)
|
||||
end,
|
||||
})
|
||||
}, function(ev)
|
||||
local detached_client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
detach(detached_client, bufnr)
|
||||
end)
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
nvim_on('LspAttach', nil, {
|
||||
desc = 'Enable on-type formatting for all buffers with individually-enabled clients.',
|
||||
callback = function(ev)
|
||||
local buf = ev.buf
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client._otf_enabled then
|
||||
attach(client, buf)
|
||||
end
|
||||
end,
|
||||
})
|
||||
}, function(ev)
|
||||
local buf = ev.buf
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client._otf_enabled then
|
||||
attach(client, buf)
|
||||
end
|
||||
end)
|
||||
|
||||
---@param enable boolean
|
||||
---@param client vim.lsp.Client
|
||||
@@ -203,16 +201,14 @@ local function toggle_globally(enable)
|
||||
-- If disabling, only clear the attachment autocmd. If enabling, create it as well.
|
||||
local group = api.nvim_create_augroup('nvim.lsp.on_type_formatting', { clear = true })
|
||||
if enable then
|
||||
api.nvim_create_autocmd('LspAttach', {
|
||||
group = group,
|
||||
nvim_on('LspAttach', group, {
|
||||
desc = 'Enable on-type formatting for ALL clients by default.',
|
||||
callback = function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client._otf_enabled ~= false then
|
||||
attach(client, ev.buf)
|
||||
end
|
||||
end,
|
||||
})
|
||||
}, function(ev)
|
||||
local client = assert(lsp.get_client_by_id(ev.data.client_id))
|
||||
if client._otf_enabled ~= false then
|
||||
attach(client, ev.buf)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local bit = require('bit')
|
||||
local util = require('vim.lsp.util')
|
||||
local Range = require('vim.treesitter._range')
|
||||
@@ -257,22 +258,14 @@ function STHighlighter:on_attach(client_id)
|
||||
self.client_state[client_id] = state
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd({ 'BufWinEnter', 'InsertLeave' }, {
|
||||
buf = self.bufnr,
|
||||
group = self.augroup,
|
||||
callback = function()
|
||||
self:send_request()
|
||||
end,
|
||||
})
|
||||
nvim_on({ 'BufWinEnter', 'InsertLeave' }, self.augroup, { buf = self.bufnr }, function()
|
||||
self:send_request()
|
||||
end)
|
||||
|
||||
if state.supports_range then
|
||||
api.nvim_create_autocmd('WinScrolled', {
|
||||
buf = self.bufnr,
|
||||
group = self.augroup,
|
||||
callback = function()
|
||||
self:on_change()
|
||||
end,
|
||||
})
|
||||
nvim_on('WinScrolled', self.augroup, { buf = self.bufnr }, function()
|
||||
self:on_change()
|
||||
end)
|
||||
end
|
||||
|
||||
self:send_request()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local protocol = require('vim.lsp.protocol')
|
||||
local validate = vim.validate
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local list_extend = vim.list_extend
|
||||
local uv = vim.uv
|
||||
|
||||
@@ -1320,28 +1321,20 @@ local function close_preview_autocmd(events, winnr, floating_bufnr, bufnr)
|
||||
|
||||
-- close the preview window when entered a buffer that is not
|
||||
-- the floating window buffer or the buffer that spawned it
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
group = augroup,
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
vim.schedule(function()
|
||||
-- When jumping to the quickfix window from the preview window,
|
||||
-- do not close the preview window.
|
||||
if api.nvim_get_option_value('filetype', { buf = 0 }) ~= 'qf' then
|
||||
close_preview_window(winnr, { floating_bufnr, bufnr })
|
||||
end
|
||||
end)
|
||||
end,
|
||||
})
|
||||
nvim_on('BufLeave', augroup, { buf = bufnr }, function()
|
||||
vim.schedule(function()
|
||||
-- When jumping to the quickfix window from the preview window,
|
||||
-- do not close the preview window.
|
||||
if api.nvim_get_option_value('filetype', { buf = 0 }) ~= 'qf' then
|
||||
close_preview_window(winnr, { floating_bufnr, bufnr })
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
if #events > 0 then
|
||||
api.nvim_create_autocmd(events, {
|
||||
group = augroup,
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
close_preview_window(winnr)
|
||||
end,
|
||||
})
|
||||
nvim_on(events, augroup, { buf = bufnr }, function()
|
||||
close_preview_window(winnr)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1593,9 +1586,10 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
api.nvim_win_set_var(floating_winnr, 'lsp_floating_bufnr', bufnr)
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('WinClosed', {
|
||||
group = api.nvim_create_augroup('nvim.closing_floating_preview', { clear = true }),
|
||||
callback = function(args)
|
||||
nvim_on(
|
||||
'WinClosed',
|
||||
api.nvim_create_augroup('nvim.closing_floating_preview', { clear = true }),
|
||||
function(args)
|
||||
local winid = vim._tointeger(args.match)
|
||||
local preview_bufnr = vim.w[winid].lsp_floating_bufnr
|
||||
if
|
||||
@@ -1606,8 +1600,8 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
vim.b[bufnr].lsp_floating_preview = nil
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
)
|
||||
|
||||
vim.wo[floating_winnr].foldenable = false -- Disable folding.
|
||||
vim.wo[floating_winnr].wrap = opts.wrap -- Soft wrapping.
|
||||
|
||||
@@ -232,6 +232,7 @@ local api = vim.api
|
||||
local uv = vim.uv
|
||||
local async = require('vim._async')
|
||||
local util = require('vim._core.util')
|
||||
local nvim_on = util.nvim_on
|
||||
local N_ = vim.fn.gettext
|
||||
|
||||
local M = {}
|
||||
@@ -1199,7 +1200,7 @@ local function show_confirm_buf(lines, on_finish)
|
||||
delete_buffer()
|
||||
end
|
||||
-- - Use `nested` to allow other events (useful for statuslines)
|
||||
api.nvim_create_autocmd('BufWriteCmd', { buf = bufnr, nested = true, callback = finish })
|
||||
nvim_on('BufWriteCmd', nil, { buf = bufnr, nested = true }, finish)
|
||||
|
||||
-- Define action to cancel confirm
|
||||
--- @type integer
|
||||
@@ -1211,7 +1212,7 @@ local function show_confirm_buf(lines, on_finish)
|
||||
pcall(api.nvim_del_autocmd, cancel_au_id)
|
||||
delete_buffer()
|
||||
end
|
||||
cancel_au_id = api.nvim_create_autocmd('WinClosed', { nested = true, callback = on_cancel })
|
||||
cancel_au_id = nvim_on('WinClosed', nil, { nested = true }, on_cancel)
|
||||
|
||||
-- Set buffer-local options last (so that user autocmmands could override)
|
||||
vim.bo[bufnr].modified = false
|
||||
|
||||
@@ -399,103 +399,97 @@ end
|
||||
---
|
||||
--- @param bufnr integer
|
||||
local function setup_autocmds(bufnr)
|
||||
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
|
||||
group = snippet_group,
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
nvim_on({ 'CursorMoved', 'CursorMovedI' }, snippet_group, {
|
||||
desc = 'Update snippet state when the cursor moves',
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
-- Just update the tabstop in insert and select modes.
|
||||
if not vim.fn.mode():match('^[isS]') then
|
||||
return
|
||||
end
|
||||
}, function()
|
||||
-- Just update the tabstop in insert and select modes.
|
||||
if not vim.fn.mode():match('^[isS]') then
|
||||
return
|
||||
end
|
||||
|
||||
local cursor_row, cursor_col = cursor_pos()
|
||||
local cursor_row, cursor_col = cursor_pos()
|
||||
|
||||
-- The cursor left the snippet region.
|
||||
local snippet_range = get_extmark_range(bufnr, M._session.extmark_id)
|
||||
if
|
||||
cursor_row < snippet_range[1]
|
||||
or (cursor_row == snippet_range[1] and cursor_col < snippet_range[2])
|
||||
or cursor_row > snippet_range[3]
|
||||
or (cursor_row == snippet_range[3] and cursor_col > snippet_range[4])
|
||||
then
|
||||
M.stop()
|
||||
return true
|
||||
end
|
||||
-- The cursor left the snippet region.
|
||||
local snippet_range = get_extmark_range(bufnr, M._session.extmark_id)
|
||||
if
|
||||
cursor_row < snippet_range[1]
|
||||
or (cursor_row == snippet_range[1] and cursor_col < snippet_range[2])
|
||||
or cursor_row > snippet_range[3]
|
||||
or (cursor_row == snippet_range[3] and cursor_col > snippet_range[4])
|
||||
then
|
||||
M.stop()
|
||||
return true
|
||||
end
|
||||
|
||||
for tabstop_index, tabstops in pairs(M._session.tabstops) do
|
||||
for _, tabstop in ipairs(tabstops) do
|
||||
local range = tabstop:get_range()
|
||||
if
|
||||
(cursor_row > range[1] or (cursor_row == range[1] and cursor_col >= range[2]))
|
||||
and (cursor_row < range[3] or (cursor_row == range[3] and cursor_col <= range[4]))
|
||||
then
|
||||
if tabstop_index ~= 0 then
|
||||
return
|
||||
end
|
||||
for tabstop_index, tabstops in pairs(M._session.tabstops) do
|
||||
for _, tabstop in ipairs(tabstops) do
|
||||
local range = tabstop:get_range()
|
||||
if
|
||||
(cursor_row > range[1] or (cursor_row == range[1] and cursor_col >= range[2]))
|
||||
and (cursor_row < range[3] or (cursor_row == range[3] and cursor_col <= range[4]))
|
||||
then
|
||||
if tabstop_index ~= 0 then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- The cursor is either not on a tabstop or we reached the end, so exit the session.
|
||||
M.stop()
|
||||
return true
|
||||
end,
|
||||
})
|
||||
-- The cursor is either not on a tabstop or we reached the end, so exit the session.
|
||||
M.stop()
|
||||
return true
|
||||
end)
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI', 'TextChangedP' }, {
|
||||
group = snippet_group,
|
||||
nvim_on({ 'TextChanged', 'TextChangedI', 'TextChangedP' }, snippet_group, {
|
||||
desc = 'Update active tabstops when buffer text changes',
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
-- Check that the snippet hasn't been deleted.
|
||||
local snippet_range = get_extmark_range(M._session.bufnr, M._session.extmark_id)
|
||||
if
|
||||
(snippet_range[1] == snippet_range[3] and snippet_range[2] == snippet_range[4])
|
||||
or snippet_range[3] + 1 > vim.fn.line('$')
|
||||
then
|
||||
M.stop()
|
||||
end
|
||||
}, function()
|
||||
-- Check that the snippet hasn't been deleted.
|
||||
local snippet_range = get_extmark_range(M._session.bufnr, M._session.extmark_id)
|
||||
if
|
||||
(snippet_range[1] == snippet_range[3] and snippet_range[2] == snippet_range[4])
|
||||
or snippet_range[3] + 1 > vim.fn.line('$')
|
||||
then
|
||||
M.stop()
|
||||
end
|
||||
|
||||
if not M.active() then
|
||||
return true
|
||||
end
|
||||
if not M.active() then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Sync the tabstops in the current group.
|
||||
local current_tabstop = M._session.current_tabstop
|
||||
local current_text = current_tabstop:get_text()
|
||||
for _, tabstop in ipairs(M._session.tabstops[current_tabstop.index]) do
|
||||
if tabstop.extmark_id ~= current_tabstop.extmark_id then
|
||||
tabstop:set_text(current_text)
|
||||
end
|
||||
-- Sync the tabstops in the current group.
|
||||
local current_tabstop = M._session.current_tabstop
|
||||
local current_text = current_tabstop:get_text()
|
||||
for _, tabstop in ipairs(M._session.tabstops[current_tabstop.index]) do
|
||||
if tabstop.extmark_id ~= current_tabstop.extmark_id then
|
||||
tabstop:set_text(current_text)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
vim.api.nvim_create_autocmd('BufLeave', {
|
||||
group = snippet_group,
|
||||
nvim_on('BufLeave', snippet_group, {
|
||||
desc = 'Stop the snippet session when leaving the buffer',
|
||||
buf = bufnr,
|
||||
callback = function()
|
||||
M.stop()
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd('ModeChanged', {
|
||||
group = snippet_group,
|
||||
}, function()
|
||||
M.stop()
|
||||
end)
|
||||
|
||||
nvim_on('ModeChanged', snippet_group, {
|
||||
desc = 'Stop the snippet session when leaving select mode',
|
||||
buf = bufnr,
|
||||
callback = function(args)
|
||||
if args.match ~= 's:n' then
|
||||
}, function(args)
|
||||
if args.match ~= 's:n' then
|
||||
return
|
||||
end
|
||||
vim.schedule(function()
|
||||
if not M.active() or vim.api.nvim_get_mode().mode:match('^[siRS\19]') then
|
||||
return
|
||||
end
|
||||
vim.schedule(function()
|
||||
if not M.active() or vim.api.nvim_get_mode().mode:match('^[siRS\19]') then
|
||||
return
|
||||
end
|
||||
M.stop()
|
||||
end)
|
||||
end,
|
||||
})
|
||||
M.stop()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Expands the given snippet text.
|
||||
|
||||
@@ -3,6 +3,7 @@ local ts = vim.treesitter
|
||||
local Range = require('vim.treesitter._range')
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
---Treesitter folding is done in two steps:
|
||||
---(1) compute the fold levels with the syntax tree and cache the result (`compute_folds_levels`)
|
||||
@@ -226,14 +227,9 @@ function FoldInfo:foldupdate(bufnr, srow, erow)
|
||||
})) > 0 then
|
||||
return
|
||||
end
|
||||
api.nvim_create_autocmd('InsertLeave', {
|
||||
group = group,
|
||||
buf = bufnr,
|
||||
once = true,
|
||||
callback = function()
|
||||
self:do_foldupdate(bufnr)
|
||||
end,
|
||||
})
|
||||
nvim_on('InsertLeave', group, { buf = bufnr, once = true }, function()
|
||||
self:do_foldupdate(bufnr)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -391,13 +387,9 @@ function M.foldexpr(lnum)
|
||||
|
||||
if not foldinfos[bufnr] then
|
||||
foldinfos[bufnr] = FoldInfo.new(bufnr)
|
||||
api.nvim_create_autocmd({ 'BufUnload', 'VimEnter', 'FileType' }, {
|
||||
buf = bufnr,
|
||||
once = true,
|
||||
callback = function()
|
||||
foldinfos[bufnr] = nil
|
||||
end,
|
||||
})
|
||||
nvim_on({ 'BufUnload', 'VimEnter', 'FileType' }, nil, { buf = bufnr, once = true }, function()
|
||||
foldinfos[bufnr] = nil
|
||||
end)
|
||||
|
||||
local parser = foldinfos[bufnr].parser
|
||||
if not parser then
|
||||
@@ -441,28 +433,27 @@ function M.foldexpr(lnum)
|
||||
return foldinfos[bufnr].levels[lnum] or '0'
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd('OptionSet', {
|
||||
nvim_on('OptionSet', group, {
|
||||
pattern = { 'foldminlines', 'foldnestmax' },
|
||||
desc = 'Refresh treesitter folds',
|
||||
callback = function()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
local bufs = vim.v.option_type == 'global' and vim.tbl_keys(foldinfos)
|
||||
or foldinfos[buf] and { buf }
|
||||
or {}
|
||||
for _, bufnr in ipairs(bufs) do
|
||||
local foldinfo = FoldInfo.new(bufnr)
|
||||
foldinfos[bufnr] = foldinfo
|
||||
api.nvim_buf_call(bufnr, function()
|
||||
compute_folds_levels(bufnr, foldinfo, nil, nil, function()
|
||||
-- FileType/BufUnload can clear or replace the fold state while this
|
||||
-- async parse is in flight. Ignore callbacks for stale generations.
|
||||
if foldinfos[bufnr] ~= foldinfo then
|
||||
return
|
||||
end
|
||||
foldinfo:foldupdate(bufnr, 0, api.nvim_buf_line_count(bufnr))
|
||||
end)
|
||||
}, function()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
local bufs = vim.v.option_type == 'global' and vim.tbl_keys(foldinfos)
|
||||
or foldinfos[buf] and { buf }
|
||||
or {}
|
||||
for _, bufnr in ipairs(bufs) do
|
||||
local foldinfo = FoldInfo.new(bufnr)
|
||||
foldinfos[bufnr] = foldinfo
|
||||
api.nvim_buf_call(bufnr, function()
|
||||
compute_folds_levels(bufnr, foldinfo, nil, nil, function()
|
||||
-- FileType/BufUnload can clear or replace the fold state while this
|
||||
-- async parse is in flight. Ignore callbacks for stale generations.
|
||||
if foldinfos[bufnr] ~= foldinfo then
|
||||
return
|
||||
end
|
||||
foldinfo:foldupdate(bufnr, 0, api.nvim_buf_line_count(bufnr))
|
||||
end)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end)
|
||||
end
|
||||
end)
|
||||
return M
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local Range = require('vim.treesitter._range')
|
||||
|
||||
@@ -469,107 +470,83 @@ function M.inspect_tree(opts)
|
||||
|
||||
local group = api.nvim_create_augroup('nvim.treesitter.dev', {})
|
||||
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
group = group,
|
||||
buf = b,
|
||||
callback = function()
|
||||
if not api.nvim_buf_is_loaded(buf) then
|
||||
return true
|
||||
end
|
||||
|
||||
w = api.nvim_get_current_win()
|
||||
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
|
||||
local row = api.nvim_win_get_cursor(w)[1]
|
||||
local lnum, col, end_lnum, end_col = treeview:get(row).node:range()
|
||||
api.nvim_buf_set_extmark(buf, treeview.ns, lnum, col, {
|
||||
end_row = end_lnum,
|
||||
end_col = math.max(0, end_col),
|
||||
hl_group = 'Visual',
|
||||
})
|
||||
|
||||
-- update source window if original was closed
|
||||
if not api.nvim_win_is_valid(win) then
|
||||
win = assert(vim.fn.win_findbuf(buf)[1])
|
||||
end
|
||||
|
||||
local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win)
|
||||
|
||||
-- Move the cursor if highlighted range is completely out of view
|
||||
if lnum < topline and end_lnum < topline then
|
||||
api.nvim_win_set_cursor(win, { end_lnum + 1, 0 })
|
||||
elseif lnum > botline and end_lnum > botline then
|
||||
api.nvim_win_set_cursor(win, { lnum + 1, 0 })
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
group = group,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
if not api.nvim_buf_is_loaded(b) then
|
||||
return true
|
||||
end
|
||||
|
||||
set_inspector_cursor(treeview, opts.lang, buf, b, w)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave' }, {
|
||||
group = group,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
if not api.nvim_buf_is_loaded(b) then
|
||||
return true
|
||||
end
|
||||
|
||||
local treeview_opts = treeview.opts
|
||||
treeview = assert(TSTreeView:new(buf, opts.lang))
|
||||
treeview.opts = treeview_opts
|
||||
treeview:draw(b)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
group = group,
|
||||
buf = b,
|
||||
callback = function()
|
||||
if not api.nvim_buf_is_loaded(buf) then
|
||||
return true
|
||||
end
|
||||
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
group = group,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
if not api.nvim_buf_is_loaded(b) then
|
||||
return true
|
||||
end
|
||||
api.nvim_buf_clear_namespace(b, treeview.ns, 0, -1)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd({ 'BufHidden', 'BufUnload', 'QuitPre' }, {
|
||||
group = group,
|
||||
buf = buf,
|
||||
callback = function()
|
||||
-- don't close inpector window if source buffer
|
||||
-- has more than one open window
|
||||
if #vim.fn.win_findbuf(buf) > 1 then
|
||||
return
|
||||
end
|
||||
|
||||
-- close all tree windows
|
||||
for _, window in pairs(vim.fn.win_findbuf(b)) do
|
||||
close_win(window)
|
||||
end
|
||||
|
||||
nvim_on('CursorMoved', group, { buf = b }, function()
|
||||
if not api.nvim_buf_is_loaded(buf) then
|
||||
return true
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
w = api.nvim_get_current_win()
|
||||
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
|
||||
local row = api.nvim_win_get_cursor(w)[1]
|
||||
local lnum, col, end_lnum, end_col = treeview:get(row).node:range()
|
||||
api.nvim_buf_set_extmark(buf, treeview.ns, lnum, col, {
|
||||
end_row = end_lnum,
|
||||
end_col = math.max(0, end_col),
|
||||
hl_group = 'Visual',
|
||||
})
|
||||
|
||||
-- update source window if original was closed
|
||||
if not api.nvim_win_is_valid(win) then
|
||||
win = assert(vim.fn.win_findbuf(buf)[1])
|
||||
end
|
||||
|
||||
local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win)
|
||||
|
||||
-- Move the cursor if highlighted range is completely out of view
|
||||
if lnum < topline and end_lnum < topline then
|
||||
api.nvim_win_set_cursor(win, { end_lnum + 1, 0 })
|
||||
elseif lnum > botline and end_lnum > botline then
|
||||
api.nvim_win_set_cursor(win, { lnum + 1, 0 })
|
||||
end
|
||||
end)
|
||||
|
||||
nvim_on('CursorMoved', group, { buf = buf }, function()
|
||||
if not api.nvim_buf_is_loaded(b) then
|
||||
return true
|
||||
end
|
||||
|
||||
set_inspector_cursor(treeview, opts.lang, buf, b, w)
|
||||
end)
|
||||
|
||||
nvim_on({ 'TextChanged', 'InsertLeave' }, group, { buf = buf }, function()
|
||||
if not api.nvim_buf_is_loaded(b) then
|
||||
return true
|
||||
end
|
||||
|
||||
local treeview_opts = treeview.opts
|
||||
treeview = assert(TSTreeView:new(buf, opts.lang))
|
||||
treeview.opts = treeview_opts
|
||||
treeview:draw(b)
|
||||
end)
|
||||
|
||||
nvim_on('BufLeave', group, { buf = b }, function()
|
||||
if not api.nvim_buf_is_loaded(buf) then
|
||||
return true
|
||||
end
|
||||
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
|
||||
end)
|
||||
|
||||
nvim_on('BufLeave', group, { buf = buf }, function()
|
||||
if not api.nvim_buf_is_loaded(b) then
|
||||
return true
|
||||
end
|
||||
api.nvim_buf_clear_namespace(b, treeview.ns, 0, -1)
|
||||
end)
|
||||
|
||||
nvim_on({ 'BufHidden', 'BufUnload', 'QuitPre' }, group, { buf = buf }, function()
|
||||
-- don't close inpector window if source buffer
|
||||
-- has more than one open window
|
||||
if #vim.fn.win_findbuf(buf) > 1 then
|
||||
return
|
||||
end
|
||||
|
||||
-- close all tree windows
|
||||
for _, window in pairs(vim.fn.win_findbuf(b)) do
|
||||
close_win(window)
|
||||
end
|
||||
|
||||
return true
|
||||
end)
|
||||
end
|
||||
|
||||
local edit_ns = api.nvim_create_namespace('nvim.treesitter.dev_edit')
|
||||
@@ -671,53 +648,43 @@ function M.edit_query(lang)
|
||||
api.nvim_buf_set_name(query_buf, string.format('%s/query_editor.scm', lang))
|
||||
|
||||
local group = api.nvim_create_augroup('nvim.treesitter.dev_edit', {})
|
||||
api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave' }, {
|
||||
group = group,
|
||||
nvim_on({ 'TextChanged', 'InsertLeave' }, group, {
|
||||
buf = query_buf,
|
||||
desc = 'Update query editor diagnostics when the query changes',
|
||||
callback = function()
|
||||
vim.treesitter.query.lint(query_buf, { langs = lang, clear = false })
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave', 'CursorMoved', 'BufEnter' }, {
|
||||
group = group,
|
||||
}, function()
|
||||
vim.treesitter.query.lint(query_buf, { langs = lang, clear = false })
|
||||
end)
|
||||
nvim_on({ 'TextChanged', 'InsertLeave', 'CursorMoved', 'BufEnter' }, group, {
|
||||
buf = query_buf,
|
||||
desc = 'Update query editor highlights when the cursor moves',
|
||||
callback = function()
|
||||
if api.nvim_win_is_valid(win) then
|
||||
update_editor_highlights(query_win, win, lang)
|
||||
end
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
group = group,
|
||||
}, function()
|
||||
if api.nvim_win_is_valid(win) then
|
||||
update_editor_highlights(query_win, win, lang)
|
||||
end
|
||||
end)
|
||||
nvim_on('BufLeave', group, {
|
||||
buf = query_buf,
|
||||
desc = 'Clear highlights when leaving the query editor',
|
||||
callback = function()
|
||||
api.nvim_buf_clear_namespace(buf, edit_ns, 0, -1)
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
group = group,
|
||||
}, function()
|
||||
api.nvim_buf_clear_namespace(buf, edit_ns, 0, -1)
|
||||
end)
|
||||
nvim_on('BufLeave', group, {
|
||||
buf = buf,
|
||||
desc = 'Clear the query editor highlights when leaving the source buffer',
|
||||
callback = function()
|
||||
if not api.nvim_buf_is_loaded(query_buf) then
|
||||
return true
|
||||
end
|
||||
}, function()
|
||||
if not api.nvim_buf_is_loaded(query_buf) then
|
||||
return true
|
||||
end
|
||||
|
||||
api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1)
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, {
|
||||
group = group,
|
||||
api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1)
|
||||
end)
|
||||
nvim_on({ 'BufHidden', 'BufUnload' }, group, {
|
||||
buf = buf,
|
||||
desc = 'Close the editor window when the source buffer is hidden or unloaded',
|
||||
once = true,
|
||||
callback = function()
|
||||
close_win(query_win)
|
||||
end,
|
||||
})
|
||||
}, function()
|
||||
close_win(query_win)
|
||||
end)
|
||||
|
||||
api.nvim_buf_set_lines(query_buf, 0, -1, false, {
|
||||
';; Write queries here (see $VIMRUNTIME/queries/ for examples).',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
--- text. See |vim.treesitter.query.parse()| for a working example.
|
||||
|
||||
local api = vim.api
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
local language = require('vim.treesitter.language')
|
||||
local memoize = vim.func._memoize
|
||||
local cmp_ge = require('vim.treesitter._range').cmp_pos.ge
|
||||
@@ -333,14 +334,17 @@ M.get = memoize('concat-2', function(lang, query_name)
|
||||
return M.parse(lang, query_string)
|
||||
end, false)
|
||||
|
||||
api.nvim_create_autocmd('OptionSet', {
|
||||
pattern = { 'runtimepath' },
|
||||
group = api.nvim_create_augroup('nvim.treesitter.query_cache_reset', { clear = true }),
|
||||
callback = function()
|
||||
nvim_on(
|
||||
'OptionSet',
|
||||
api.nvim_create_augroup('nvim.treesitter.query_cache_reset', { clear = true }),
|
||||
{
|
||||
pattern = { 'runtimepath' },
|
||||
},
|
||||
function()
|
||||
--- @diagnostic disable-next-line: undefined-field LuaLS bad at generics
|
||||
M.get:clear()
|
||||
end,
|
||||
})
|
||||
end
|
||||
)
|
||||
|
||||
--- Parses a {query} string and returns a `Query` object (|lua-treesitter-query|), which can be used
|
||||
--- to search the tree for the query patterns (via |Query:iter_captures()|, |Query:iter_matches()|),
|
||||
|
||||
@@ -28,18 +28,19 @@ function M.request(payload, opts, on_response)
|
||||
timer = assert(vim.uv.new_timer())
|
||||
end
|
||||
|
||||
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
||||
group = opts.group,
|
||||
nested = true,
|
||||
callback = function(ev)
|
||||
local id = require('vim._core.util').nvim_on(
|
||||
'TermResponse',
|
||||
opts.group,
|
||||
{ nested = true },
|
||||
function(ev)
|
||||
local stop = on_response(ev.data.sequence)
|
||||
-- If on_response is done, cancel the timeout so on_timeout doesn't fire spuriously.
|
||||
if stop and timer and not timer:is_closing() then
|
||||
timer:close()
|
||||
end
|
||||
return stop
|
||||
end,
|
||||
})
|
||||
end
|
||||
)
|
||||
|
||||
if payload ~= '' then
|
||||
vim.api.nvim_ui_send(payload)
|
||||
|
||||
@@ -342,11 +342,13 @@ do
|
||||
--- Initialize Progress handlers.
|
||||
local function progress_init()
|
||||
progress_group = vim.api.nvim_create_augroup('nvim.ui.progress_status', { clear = true })
|
||||
progress_autocmd = vim.api.nvim_create_autocmd('Progress', {
|
||||
group = progress_group,
|
||||
desc = 'Tracks progress messages for vim.ui.progress_status()',
|
||||
---@param ev {data: vim.event.progress.data}
|
||||
callback = function(ev)
|
||||
progress_autocmd = require('vim._core.util').nvim_on(
|
||||
'Progress',
|
||||
progress_group,
|
||||
{
|
||||
desc = 'Tracks progress messages for vim.ui.progress_status()',
|
||||
}, ---@param ev {data: vim.event.progress.data}
|
||||
function(ev)
|
||||
if not ev.data or not ev.data.id then
|
||||
return
|
||||
end
|
||||
@@ -362,8 +364,8 @@ do
|
||||
then
|
||||
progress[ev.data.id] = nil
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
--- Gets a status description summarizing currently running progress messages.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
local nvim_on = require('vim._core.util').nvim_on
|
||||
|
||||
local M = {}
|
||||
|
||||
---@brief
|
||||
@@ -142,10 +144,8 @@ function M._supported(opts)
|
||||
return require('vim.ui.img._kitty').supported(opts)
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd('VimLeavePre', {
|
||||
callback = function()
|
||||
M.del(math.huge)
|
||||
end,
|
||||
})
|
||||
nvim_on('VimLeavePre', nil, function()
|
||||
M.del(math.huge)
|
||||
end)
|
||||
|
||||
return M
|
||||
|
||||
@@ -324,13 +324,10 @@ describe('startup', function()
|
||||
os.remove('Xtest_shada')
|
||||
end)
|
||||
|
||||
assert_l_out(
|
||||
'updatecount=0 shadafile=NONE loadplugins=false scripts=1\n',
|
||||
nil,
|
||||
nil,
|
||||
'-',
|
||||
script
|
||||
)
|
||||
assert_l_out(function(out)
|
||||
-- Accept scripts=2 for PUC Lua where `vim._core.util` is sourced from disk instead of a preload blob.
|
||||
return matches('updatecount=0 shadafile=NONE loadplugins=false scripts=[12]\n', out)
|
||||
end, nil, nil, '-', script)
|
||||
|
||||
-- User can override.
|
||||
assert_l_out(
|
||||
|
||||
Reference in New Issue
Block a user