mirror of
https://github.com/neovim/neovim.git
synced 2025-10-07 18:36:30 +00:00
Merge #34919 feat(vim.pack): more actions in confirm-update
This commit is contained in:
@@ -393,14 +393,18 @@ update({names}, {opts}) *vim.pack.update()*
|
|||||||
• Depending on `force`:
|
• Depending on `force`:
|
||||||
• If `false`, show confirmation buffer. It lists data about all set to
|
• If `false`, show confirmation buffer. It lists data about all set to
|
||||||
update plugins. Pending changes starting with `>` will be applied
|
update plugins. Pending changes starting with `>` will be applied
|
||||||
while the ones starting with `<` will be reverted. It has special
|
while the ones starting with `<` will be reverted. It has dedicated
|
||||||
in-process LSP server attached to provide more interactive features.
|
buffer-local mappings:
|
||||||
Currently supported methods:
|
• |]]| and |[[| to navigate through plugin sections.
|
||||||
|
Some features are provided via LSP:
|
||||||
• 'textDocument/documentSymbol' (`gO` via |lsp-defaults| or
|
• 'textDocument/documentSymbol' (`gO` via |lsp-defaults| or
|
||||||
|vim.lsp.buf.document_symbol()|) - show structure of the buffer.
|
|vim.lsp.buf.document_symbol()|) - show structure of the buffer.
|
||||||
• 'textDocument/hover' (`K` via |lsp-defaults| or
|
• 'textDocument/hover' (`K` via |lsp-defaults| or
|
||||||
|vim.lsp.buf.hover()|) - show more information at cursor. Like
|
|vim.lsp.buf.hover()|) - show more information at cursor. Like
|
||||||
details of particular pending change or newer tag.
|
details of particular pending change or newer tag.
|
||||||
|
• 'textDocument/codeAction' (`gra` via |lsp-defaults| or
|
||||||
|
|vim.lsp.buf.code_action()|) - show code actions available for
|
||||||
|
"plugin at cursor". Like "delete", "update", or "skip updating".
|
||||||
Execute |:write| to confirm update, execute |:quit| to discard the
|
Execute |:write| to confirm update, execute |:quit| to discard the
|
||||||
update.
|
update.
|
||||||
• If `true`, make updates right away.
|
• If `true`, make updates right away.
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
-- Highlighting
|
||||||
local ns = vim.api.nvim_create_namespace('nvim.pack.confirm')
|
local ns = vim.api.nvim_create_namespace('nvim.pack.confirm')
|
||||||
vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||||
|
|
||||||
@@ -49,3 +50,15 @@ for i, l in ipairs(lines) do
|
|||||||
hi_range(i, 4, l:len(), 'DiagnosticHint')
|
hi_range(i, 4, l:len(), 'DiagnosticHint')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Mappings
|
||||||
|
local map_section_jump = function(lhs, search_flags, desc)
|
||||||
|
vim.keymap.set({ 'n', 'x' }, lhs, function()
|
||||||
|
for _ = 1, vim.v.count1 do
|
||||||
|
vim.fn.search('^## ', search_flags)
|
||||||
|
end
|
||||||
|
end, { buffer = 0, desc = desc })
|
||||||
|
end
|
||||||
|
|
||||||
|
map_section_jump('[[', 'bsW', 'Previous plugin')
|
||||||
|
map_section_jump(']]', 'sW', 'Next plugin')
|
||||||
|
@@ -897,7 +897,7 @@ local function feedback_log(plug_list)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- @param lines string[]
|
--- @param lines string[]
|
||||||
--- @param on_finish fun()
|
--- @param on_finish fun(bufnr: integer)
|
||||||
local function show_confirm_buf(lines, on_finish)
|
local function show_confirm_buf(lines, on_finish)
|
||||||
-- Show buffer in a separate tabpage
|
-- Show buffer in a separate tabpage
|
||||||
local bufnr = api.nvim_create_buf(true, true)
|
local bufnr = api.nvim_create_buf(true, true)
|
||||||
@@ -917,7 +917,7 @@ local function show_confirm_buf(lines, on_finish)
|
|||||||
|
|
||||||
-- Define action on accepting confirm
|
-- Define action on accepting confirm
|
||||||
local function finish()
|
local function finish()
|
||||||
on_finish()
|
on_finish(bufnr)
|
||||||
delete_buffer()
|
delete_buffer()
|
||||||
end
|
end
|
||||||
-- - Use `nested` to allow other events (useful for statuslines)
|
-- - Use `nested` to allow other events (useful for statuslines)
|
||||||
@@ -945,6 +945,28 @@ local function show_confirm_buf(lines, on_finish)
|
|||||||
vim.lsp.buf_attach_client(bufnr, require('vim.pack._lsp').client_id)
|
vim.lsp.buf_attach_client(bufnr, require('vim.pack._lsp').client_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get map of plugin names that need update based on confirmation buffer
|
||||||
|
--- content: all plugin sections present in "# Update" section.
|
||||||
|
--- @param bufnr integer
|
||||||
|
--- @return table<string,boolean>
|
||||||
|
local function get_update_map(bufnr)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
--- @type table<string,boolean>, boolean
|
||||||
|
local res, is_in_update = {}, false
|
||||||
|
for _, l in ipairs(lines) do
|
||||||
|
local name = l:match('^## (.+)$')
|
||||||
|
if name and is_in_update then
|
||||||
|
res[name] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local group = l:match('^# (%S+)')
|
||||||
|
if group then
|
||||||
|
is_in_update = group == 'Update'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
--- @class vim.pack.keyset.update
|
--- @class vim.pack.keyset.update
|
||||||
--- @inlinedoc
|
--- @inlinedoc
|
||||||
--- @field force? boolean Whether to skip confirmation and make updates immediately. Default `false`.
|
--- @field force? boolean Whether to skip confirmation and make updates immediately. Default `false`.
|
||||||
@@ -957,13 +979,18 @@ end
|
|||||||
--- - If `false`, show confirmation buffer. It lists data about all set to
|
--- - If `false`, show confirmation buffer. It lists data about all set to
|
||||||
--- update plugins. Pending changes starting with `>` will be applied while
|
--- update plugins. Pending changes starting with `>` will be applied while
|
||||||
--- the ones starting with `<` will be reverted.
|
--- the ones starting with `<` will be reverted.
|
||||||
--- It has special in-process LSP server attached to provide more interactive
|
--- It has dedicated buffer-local mappings:
|
||||||
--- features. Currently supported methods:
|
--- - |]]| and |[[| to navigate through plugin sections.
|
||||||
|
---
|
||||||
|
--- Some features are provided via LSP:
|
||||||
--- - 'textDocument/documentSymbol' (`gO` via |lsp-defaults|
|
--- - 'textDocument/documentSymbol' (`gO` via |lsp-defaults|
|
||||||
--- or |vim.lsp.buf.document_symbol()|) - show structure of the buffer.
|
--- or |vim.lsp.buf.document_symbol()|) - show structure of the buffer.
|
||||||
--- - 'textDocument/hover' (`K` via |lsp-defaults| or |vim.lsp.buf.hover()|) -
|
--- - 'textDocument/hover' (`K` via |lsp-defaults| or |vim.lsp.buf.hover()|) -
|
||||||
--- show more information at cursor. Like details of particular pending
|
--- show more information at cursor. Like details of particular pending
|
||||||
--- change or newer tag.
|
--- change or newer tag.
|
||||||
|
--- - 'textDocument/codeAction' (`gra` via |lsp-defaults| or |vim.lsp.buf.code_action()|) -
|
||||||
|
--- show code actions available for "plugin at cursor". Like "delete", "update",
|
||||||
|
--- or "skip updating".
|
||||||
---
|
---
|
||||||
--- Execute |:write| to confirm update, execute |:quit| to discard the update.
|
--- Execute |:write| to confirm update, execute |:quit| to discard the update.
|
||||||
--- - If `true`, make updates right away.
|
--- - If `true`, make updates right away.
|
||||||
@@ -994,11 +1021,11 @@ function M.update(names, opts)
|
|||||||
--- @param p vim.pack.Plug
|
--- @param p vim.pack.Plug
|
||||||
local function do_update(p)
|
local function do_update(p)
|
||||||
-- Fetch
|
-- Fetch
|
||||||
-- Using '--tags --force' means conflicting tags will be synced with remote
|
if not opts._offline then
|
||||||
git_cmd(
|
-- Using '--tags --force' means conflicting tags will be synced with remote
|
||||||
{ 'fetch', '--quiet', '--tags', '--force', '--recurse-submodules=yes', 'origin' },
|
local args = { 'fetch', '--quiet', '--tags', '--force', '--recurse-submodules=yes', 'origin' }
|
||||||
p.path
|
git_cmd(args, p.path)
|
||||||
)
|
end
|
||||||
|
|
||||||
-- Compute change info: changelog if any, new tags if nothing to update
|
-- Compute change info: changelog if any, new tags if nothing to update
|
||||||
infer_update_details(p)
|
infer_update_details(p)
|
||||||
@@ -1008,7 +1035,8 @@ function M.update(names, opts)
|
|||||||
checkout(p, timestamp, true)
|
checkout(p, timestamp, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local progress_title = opts.force and 'Updating' or 'Downloading updates'
|
local progress_title = opts.force and (opts._offline and 'Applying updates' or 'Updating')
|
||||||
|
or 'Downloading updates'
|
||||||
run_list(plug_list, do_update, progress_title)
|
run_list(plug_list, do_update, progress_title)
|
||||||
|
|
||||||
if opts.force then
|
if opts.force then
|
||||||
@@ -1019,17 +1047,18 @@ function M.update(names, opts)
|
|||||||
|
|
||||||
-- Show report in new buffer in separate tabpage
|
-- Show report in new buffer in separate tabpage
|
||||||
local lines = compute_feedback_lines(plug_list, false)
|
local lines = compute_feedback_lines(plug_list, false)
|
||||||
show_confirm_buf(lines, function()
|
show_confirm_buf(lines, function(bufnr)
|
||||||
-- TODO(echasnovski): Allow to not update all plugins via LSP code actions
|
local to_update = get_update_map(bufnr)
|
||||||
--- @param p vim.pack.Plug
|
if not next(to_update) then
|
||||||
local plugs_to_checkout = vim.tbl_filter(function(p)
|
|
||||||
return p.info.err == '' and p.info.sha_head ~= p.info.sha_target
|
|
||||||
end, plug_list)
|
|
||||||
if #plugs_to_checkout == 0 then
|
|
||||||
notify('Nothing to update', 'WARN')
|
notify('Nothing to update', 'WARN')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @param p vim.pack.Plug
|
||||||
|
local plugs_to_checkout = vim.tbl_filter(function(p)
|
||||||
|
return to_update[p.spec.name]
|
||||||
|
end, plug_list)
|
||||||
|
|
||||||
local timestamp2 = get_timestamp()
|
local timestamp2 = get_timestamp()
|
||||||
--- @async
|
--- @async
|
||||||
--- @param p vim.pack.Plug
|
--- @param p vim.pack.Plug
|
||||||
|
@@ -3,6 +3,7 @@ local M = {}
|
|||||||
local capabilities = {
|
local capabilities = {
|
||||||
codeActionProvider = true,
|
codeActionProvider = true,
|
||||||
documentSymbolProvider = true,
|
documentSymbolProvider = true,
|
||||||
|
executeCommandProvider = { commands = { 'delete_plugin', 'update_plugin', 'skip_update_plugin' } },
|
||||||
hoverProvider = true,
|
hoverProvider = true,
|
||||||
}
|
}
|
||||||
--- @type table<string,function>
|
--- @type table<string,function>
|
||||||
@@ -22,6 +23,48 @@ local get_confirm_bufnr = function(uri)
|
|||||||
return tonumber(uri:match('^nvim%-pack://(%d+)/confirm%-update$'))
|
return tonumber(uri:match('^nvim%-pack://(%d+)/confirm%-update$'))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local group_header_pattern = '^# (%S+)'
|
||||||
|
local plugin_header_pattern = '^## (.+)$'
|
||||||
|
|
||||||
|
--- @return { group: string?, name: string?, from: integer?, to: integer? }
|
||||||
|
local get_plug_data_at_lnum = function(bufnr, lnum)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
--- @type string, string, integer, integer
|
||||||
|
local group, name, from, to
|
||||||
|
for i = lnum, 1, -1 do
|
||||||
|
group = group or lines[i]:match(group_header_pattern) --[[@as string]]
|
||||||
|
-- If group is found earlier than name - `lnum` is for group header line
|
||||||
|
-- If later - proper group header line.
|
||||||
|
if group then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
name = name or lines[i]:match(plugin_header_pattern) --[[@as string]]
|
||||||
|
from = (not from and name) and i or from --[[@as integer]]
|
||||||
|
end
|
||||||
|
if not (group and name and from) then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
--- @cast group string
|
||||||
|
--- @cast from integer
|
||||||
|
|
||||||
|
for i = lnum + 1, #lines do
|
||||||
|
if lines[i]:match(group_header_pattern) or lines[i]:match(plugin_header_pattern) then
|
||||||
|
-- Do not include blank line before next section
|
||||||
|
to = i - 2
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
to = to or #lines
|
||||||
|
|
||||||
|
if not (from <= lnum and lnum <= to) then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
return { group = group, name = name, from = from, to = to }
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @alias vim.pack.lsp.Position { line: integer, character: integer }
|
||||||
|
--- @alias vim.pack.lsp.Range { start: vim.pack.lsp.Position, end: vim.pack.lsp.Position }
|
||||||
|
|
||||||
--- @param params { textDocument: { uri: string } }
|
--- @param params { textDocument: { uri: string } }
|
||||||
--- @param callback function
|
--- @param callback function
|
||||||
methods['textDocument/documentSymbol'] = function(params, callback)
|
methods['textDocument/documentSymbol'] = function(params, callback)
|
||||||
@@ -30,8 +73,6 @@ methods['textDocument/documentSymbol'] = function(params, callback)
|
|||||||
return callback(nil, {})
|
return callback(nil, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @alias vim.pack.lsp.Position { line: integer, character: integer }
|
|
||||||
--- @alias vim.pack.lsp.Range { start: vim.pack.lsp.Position, end: vim.pack.lsp.Position }
|
|
||||||
--- @alias vim.pack.lsp.Symbol {
|
--- @alias vim.pack.lsp.Symbol {
|
||||||
--- name: string,
|
--- name: string,
|
||||||
--- kind: number,
|
--- kind: number,
|
||||||
@@ -69,28 +110,81 @@ methods['textDocument/documentSymbol'] = function(params, callback)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local group_kind = vim.lsp.protocol.SymbolKind.Namespace
|
local group_kind = vim.lsp.protocol.SymbolKind.Namespace
|
||||||
local symbols = parse_headers('^# (%S+)', 0, #lines - 1, group_kind)
|
local symbols = parse_headers(group_header_pattern, 0, #lines - 1, group_kind)
|
||||||
|
|
||||||
local plug_kind = vim.lsp.protocol.SymbolKind.Module
|
local plug_kind = vim.lsp.protocol.SymbolKind.Module
|
||||||
for _, group in ipairs(symbols) do
|
for _, group in ipairs(symbols) do
|
||||||
local start_line, end_line = group.range.start.line, group.range['end'].line
|
local start_line, end_line = group.range.start.line, group.range['end'].line
|
||||||
group.children = parse_headers('^## (.+)$', start_line, end_line, plug_kind)
|
group.children = parse_headers(plugin_header_pattern, start_line, end_line, plug_kind)
|
||||||
end
|
end
|
||||||
|
|
||||||
return callback(nil, symbols)
|
return callback(nil, symbols)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @alias vim.pack.lsp.CodeActionContext { diagnostics: table, only: table?, triggerKind: integer? }
|
||||||
|
|
||||||
|
--- @param params { textDocument: { uri: string }, range: vim.pack.lsp.Range, context: vim.pack.lsp.CodeActionContext }
|
||||||
--- @param callback function
|
--- @param callback function
|
||||||
methods['textDocument/codeAction'] = function(_, callback)
|
methods['textDocument/codeAction'] = function(params, callback)
|
||||||
-- TODO(echasnovski)
|
local bufnr = get_confirm_bufnr(params.textDocument.uri)
|
||||||
-- Suggested actions for "plugin under cursor":
|
local empty_kind = vim.lsp.protocol.CodeActionKind.Empty
|
||||||
-- - Delete plugin from disk.
|
local only = params.context.only or { empty_kind }
|
||||||
-- - Update only this plugin.
|
if not (bufnr and vim.tbl_contains(only, empty_kind)) then
|
||||||
-- - Exclude this plugin from update.
|
return callback(nil, {})
|
||||||
return callback(_, {})
|
end
|
||||||
|
local plug_data = get_plug_data_at_lnum(bufnr, params.range.start.line + 1)
|
||||||
|
if not plug_data.name then
|
||||||
|
return callback(nil, {})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function new_action(title, command)
|
||||||
|
return {
|
||||||
|
title = ('%s `%s`'):format(title, plug_data.name),
|
||||||
|
command = { title = title, command = command, arguments = { bufnr, plug_data } },
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local res = {}
|
||||||
|
if plug_data.group == 'Update' then
|
||||||
|
vim.list_extend(res, {
|
||||||
|
new_action('Update', 'update_plugin'),
|
||||||
|
new_action('Skip updating', 'skip_update_plugin'),
|
||||||
|
}, 0)
|
||||||
|
end
|
||||||
|
vim.list_extend(res, { new_action('Delete', 'delete_plugin') })
|
||||||
|
callback(nil, res)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param params { textDocument: { uri: string }, position: { line: integer, character: integer } }
|
local commands = {
|
||||||
|
update_plugin = function(plug_data)
|
||||||
|
vim.pack.update({ plug_data.name }, { force = true, _offline = true })
|
||||||
|
end,
|
||||||
|
skip_update_plugin = function(_) end,
|
||||||
|
delete_plugin = function(plug_data)
|
||||||
|
vim.pack.del({ plug_data.name })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- NOTE: Use `vim.schedule_wrap` to avoid press-enter after choosing code
|
||||||
|
-- action via built-in `vim.fn.inputlist()`
|
||||||
|
--- @param params { command: string, arguments: table }
|
||||||
|
--- @param callback function
|
||||||
|
methods['workspace/executeCommand'] = vim.schedule_wrap(function(params, callback)
|
||||||
|
--- @type integer, table
|
||||||
|
local bufnr, plug_data = unpack(params.arguments)
|
||||||
|
local ok, err = pcall(commands[params.command], plug_data)
|
||||||
|
if not ok then
|
||||||
|
return callback({ code = 1, message = err }, {})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove plugin lines (including blank line) to not later act on plugin
|
||||||
|
vim.bo[bufnr].modifiable = true
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, plug_data.from - 2, plug_data.to, false, {})
|
||||||
|
vim.bo[bufnr].modifiable, vim.bo[bufnr].modified = false, false
|
||||||
|
callback(nil, {})
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- @param params { textDocument: { uri: string }, position: vim.pack.lsp.Position }
|
||||||
--- @param callback function
|
--- @param callback function
|
||||||
methods['textDocument/hover'] = function(params, callback)
|
methods['textDocument/hover'] = function(params, callback)
|
||||||
local bufnr = get_confirm_bufnr(params.textDocument.uri)
|
local bufnr = get_confirm_bufnr(params.textDocument.uri)
|
||||||
|
@@ -1136,6 +1136,7 @@ describe('vim.pack', function()
|
|||||||
|
|
||||||
it('has in-process LSP features', function()
|
it('has in-process LSP features', function()
|
||||||
t.skip(not is_jit(), "Non LuaJIT reports errors differently due to 'coxpcall'")
|
t.skip(not is_jit(), "Non LuaJIT reports errors differently due to 'coxpcall'")
|
||||||
|
track_nvim_echo()
|
||||||
exec_lua(function()
|
exec_lua(function()
|
||||||
vim.pack.add({
|
vim.pack.add({
|
||||||
repos_src.fetch,
|
repos_src.fetch,
|
||||||
@@ -1203,6 +1204,150 @@ describe('vim.pack', function()
|
|||||||
validate_hover({ 30, 0 }, 'Add version v1.0.0')
|
validate_hover({ 30, 0 }, 'Add version v1.0.0')
|
||||||
validate_hover({ 31, 0 }, 'Add version v0.4')
|
validate_hover({ 31, 0 }, 'Add version v0.4')
|
||||||
validate_hover({ 32, 0 }, 'Add version 0.3.1')
|
validate_hover({ 32, 0 }, 'Add version 0.3.1')
|
||||||
|
|
||||||
|
-- textDocument/codeAction
|
||||||
|
n.exec_lua(function()
|
||||||
|
-- Mock `vim.ui.select()` which is a default code action selection
|
||||||
|
_G.select_idx = 0
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: duplicate-set-field
|
||||||
|
vim.ui.select = function(items, _, on_choice)
|
||||||
|
_G.select_items = items
|
||||||
|
local idx = _G.select_idx
|
||||||
|
if idx > 0 then
|
||||||
|
on_choice(items[idx], idx)
|
||||||
|
-- Minor delay before continue because LSP cmd execution is async
|
||||||
|
vim.wait(10)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local ref_lockfile = get_lock_tbl() --- @type vim.pack.Lock
|
||||||
|
|
||||||
|
local function validate_action(pos, action_titles, select_idx)
|
||||||
|
api.nvim_win_set_cursor(0, pos)
|
||||||
|
|
||||||
|
local lines = api.nvim_buf_get_lines(0, 0, -1, false)
|
||||||
|
n.exec_lua(function()
|
||||||
|
_G.select_items = nil
|
||||||
|
_G.select_idx = select_idx
|
||||||
|
vim.lsp.buf.code_action()
|
||||||
|
end)
|
||||||
|
local titles = vim.tbl_map(function(x) --- @param x table
|
||||||
|
return x.action.title
|
||||||
|
end, n.exec_lua('return _G.select_items or {}'))
|
||||||
|
eq(titles, action_titles)
|
||||||
|
|
||||||
|
-- If no action is asked (like via cancel), should not delete lines
|
||||||
|
if select_idx <= 0 then
|
||||||
|
eq(lines, api.nvim_buf_get_lines(0, 0, -1, false))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- - Should not include "namespace" header as "plugin at cursor"
|
||||||
|
validate_action({ 1, 1 }, {}, 0)
|
||||||
|
validate_action({ 2, 0 }, {}, 0)
|
||||||
|
-- - Only deletion should be available on errored plugin
|
||||||
|
validate_action({ 3, 1 }, { 'Delete `defbranch`' }, 0)
|
||||||
|
validate_action({ 7, 0 }, { 'Delete `defbranch`' }, 0)
|
||||||
|
-- - Should not include separator blank line as "plugin at cursor"
|
||||||
|
validate_action({ 8, 0 }, {}, 0)
|
||||||
|
validate_action({ 9, 0 }, {}, 0)
|
||||||
|
validate_action({ 10, 0 }, {}, 0)
|
||||||
|
-- - Should also suggest updating related actions if updates available
|
||||||
|
local fetch_actions = { 'Update `fetch`', 'Skip updating `fetch`', 'Delete `fetch`' }
|
||||||
|
validate_action({ 11, 0 }, fetch_actions, 0)
|
||||||
|
validate_action({ 14, 0 }, fetch_actions, 0)
|
||||||
|
validate_action({ 20, 0 }, fetch_actions, 0)
|
||||||
|
validate_action({ 21, 0 }, {}, 0)
|
||||||
|
validate_action({ 22, 0 }, {}, 0)
|
||||||
|
validate_action({ 23, 0 }, {}, 0)
|
||||||
|
-- - Only deletion should be available on plugins without update
|
||||||
|
validate_action({ 24, 0 }, { 'Delete `semver`' }, 0)
|
||||||
|
validate_action({ 28, 0 }, { 'Delete `semver`' }, 0)
|
||||||
|
validate_action({ 32, 0 }, { 'Delete `semver`' }, 0)
|
||||||
|
|
||||||
|
-- - Should correctly perform action and remove plugin's lines
|
||||||
|
local function line_match(lnum, pattern)
|
||||||
|
matches(pattern, api.nvim_buf_get_lines(0, lnum - 1, lnum, false)[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- - Delete. Should remove from disk and update lockfile.
|
||||||
|
validate_action({ 3, 0 }, { 'Delete `defbranch`' }, 1)
|
||||||
|
eq(false, pack_exists('defbranch'))
|
||||||
|
line_match(1, '^# Error')
|
||||||
|
line_match(2, '^$')
|
||||||
|
line_match(3, '^# Update')
|
||||||
|
|
||||||
|
ref_lockfile.plugins.defbranch = nil
|
||||||
|
eq(ref_lockfile, get_lock_tbl())
|
||||||
|
|
||||||
|
-- - Skip udating
|
||||||
|
validate_action({ 5, 0 }, fetch_actions, 2)
|
||||||
|
eq({ 'return "fetch main"' }, fn.readfile(fetch_lua_file))
|
||||||
|
line_match(3, '^# Update')
|
||||||
|
line_match(4, '^$')
|
||||||
|
line_match(5, '^# Same')
|
||||||
|
|
||||||
|
-- - Update plugin. Should not re-fetch new data and update lockfile.
|
||||||
|
n.exec('quit')
|
||||||
|
n.exec_lua(function()
|
||||||
|
vim.pack.update({ 'fetch', 'semver' })
|
||||||
|
end)
|
||||||
|
exec_lua('_G.echo_log = {}')
|
||||||
|
|
||||||
|
ref_lockfile.plugins.fetch.rev = git_get_hash('main', 'fetch')
|
||||||
|
repo_write_file('fetch', 'lua/fetch.lua', 'return "fetch new 3"')
|
||||||
|
git_add_commit('Commit to be added 3', 'fetch')
|
||||||
|
|
||||||
|
validate_action({ 3, 0 }, fetch_actions, 1)
|
||||||
|
|
||||||
|
eq({ 'return "fetch new 2"' }, fn.readfile(fetch_lua_file))
|
||||||
|
validate_progress_report('Applying updates', { 'fetch' })
|
||||||
|
line_match(1, '^# Update')
|
||||||
|
line_match(2, '^$')
|
||||||
|
line_match(3, '^# Same')
|
||||||
|
|
||||||
|
eq(ref_lockfile, get_lock_tbl())
|
||||||
|
|
||||||
|
-- - Can still respect `:write` after action
|
||||||
|
n.exec('write')
|
||||||
|
eq('vim.pack: Nothing to update', n.exec_capture('1messages'))
|
||||||
|
eq(api.nvim_get_option_value('filetype', {}), '')
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('has buffer-local mappings', function()
|
||||||
|
t.skip(not is_jit(), "Non LuaJIT reports update errors differently due to 'coxpcall'")
|
||||||
|
exec_lua(function()
|
||||||
|
vim.pack.add({
|
||||||
|
repos_src.fetch,
|
||||||
|
{ src = repos_src.semver, version = 'v0.3.0' },
|
||||||
|
{ src = repos_src.defbranch, version = 'does-not-exist' },
|
||||||
|
})
|
||||||
|
-- Enable sourcing filetype script (that creates mappings)
|
||||||
|
vim.cmd('filetype plugin on')
|
||||||
|
vim.pack.update()
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Plugin sections navigation
|
||||||
|
local validate = function(keys, ref_cursor)
|
||||||
|
n.feed(keys)
|
||||||
|
eq(ref_cursor, api.nvim_win_get_cursor(0))
|
||||||
|
end
|
||||||
|
|
||||||
|
api.nvim_win_set_cursor(0, { 1, 1 })
|
||||||
|
validate(']]', { 3, 0 })
|
||||||
|
validate(']]', { 11, 0 })
|
||||||
|
validate(']]', { 24, 0 })
|
||||||
|
-- - Should not wrap around the edge
|
||||||
|
validate(']]', { 24, 0 })
|
||||||
|
|
||||||
|
api.nvim_win_set_cursor(0, { 32, 1 })
|
||||||
|
validate('[[', { 24, 0 })
|
||||||
|
validate('[[', { 11, 0 })
|
||||||
|
validate('[[', { 3, 0 })
|
||||||
|
-- - Should not wrap around the edge
|
||||||
|
validate('[[', { 3, 0 })
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('suggests newer versions when on non-tagged commit', function()
|
it('suggests newer versions when on non-tagged commit', function()
|
||||||
|
Reference in New Issue
Block a user