refactor: Provider symbol actions

It makes sense to store the provider each sidebar is using with own
self.provider fields, no way that did not occur to me before this.

The old `_G._outline_current_provider` ironically, can now be replaced
by `require('outline').current.provider`.
This commit is contained in:
hedy
2023-11-26 15:14:42 +08:00
parent 1743ee7c66
commit b90174c6c2
8 changed files with 78 additions and 91 deletions

View File

@@ -1,14 +0,0 @@
local outline = require('outline')
local M = {}
function M.show_code_actions()
-- keep the cursor info in outline and jump back (or not jump back?)
local winnr, pos = vim.api.nvim_get_current_win(), vim.api.nvim_win_get_cursor(0)
outline.current:_goto_location(true)
vim.lsp.buf.code_action()
vim.fn.win_gotoid(winnr)
vim.api.nvim_win_set_cursor(winnr, pos)
end
return M

View File

@@ -245,18 +245,24 @@ end
function M.show_status() function M.show_status()
local sidebar = M._get_sidebar(false) local sidebar = M._get_sidebar(false)
local buf, win = 0, 0 local buf, win = 0, 0
local is_open local is_open, provider
if sidebar then if sidebar then
buf = sidebar.code.buf buf = sidebar.code.buf
win = sidebar.code.win win = sidebar.code.win
is_open = sidebar.view:is_open() is_open = sidebar.view:is_open()
provider = sidebar.provider
end
if not is_open then
provider = providers.find_provider()
end end
---@type outline.StatusContext ---@type outline.StatusContext
local ctx = { local ctx = {
priority = cfg.o.providers.priority, priority = cfg.o.providers.priority,
outline_open = is_open, outline_open = is_open,
provider = provider,
} }
if vim.api.nvim_buf_is_valid(buf) then if vim.api.nvim_buf_is_valid(buf) then
@@ -267,13 +273,7 @@ function M.show_status()
ctx.default_filter = cfg.o.symbols.user_config_filter.default ctx.default_filter = cfg.o.symbols.user_config_filter.default
local p = _G._outline_current_provider if provider ~= nil then
if not is_open then
p = providers.find_provider()
end
if p ~= nil then
ctx.provider = p
-- Just show code window is active when the first outline in this tabpage -- Just show code window is active when the first outline in this tabpage
-- has not yet been opened. -- has not yet been opened.
if not sidebar then if not sidebar then

View File

@@ -28,7 +28,7 @@ end
---@param result table ---@param result table
local function convert_symbols(result) local function convert_symbols(result)
local s = {} local s = {}
local kinds_index = require('outline.symbol').str_to_kind local kinds_index = require('outline.symbols').str_to_kind
-- rebuild coc.nvim symbol list hierarchy according to the 'level' key -- rebuild coc.nvim symbol list hierarchy according to the 'level' key
for _, value in pairs(result) do for _, value in pairs(result) do
value.children = {} value.children = {}

View File

@@ -3,19 +3,19 @@ local cfg = require('outline.config')
local M = {} local M = {}
local import_prefix = 'outline/providers/' local import_prefix = 'outline/providers/'
---@return outline.Provider?
function M.find_provider() function M.find_provider()
if not M.providers then if not M.providers then
M.providers = vim.tbl_map(function(p) M.providers = vim.tbl_map(function(p)
return import_prefix .. p return import_prefix .. p
end, cfg.get_providers()) end, cfg.get_providers())
end end
for _, name in ipairs(M.providers) do for _, path in ipairs(M.providers) do
local provider = require(name) local provider = require(path)
if provider.supports_buffer(0) then if provider.supports_buffer(0) then
return provider, name return provider
end end
end end
return nil, nil
end end
---@return boolean found_provider ---@return boolean found_provider
@@ -23,20 +23,15 @@ function M.has_provider()
return M.find_provider() ~= nil return M.find_provider() ~= nil
end end
---@param on_symbols function ---Call `sidebar.provider[method]` with args. NOP if no provider or no defined `method`
---@param opts outline.OutlineOpts? ---@param sidebar outline.Sidebar
---@return boolean found_provider ---@param method string
function M.request_symbols(on_symbols, opts) ---@param args any[]
local provider, name = M.find_provider() function M.action(sidebar, method, args)
if not provider then if not sidebar.provider or not sidebar.provider[method] then
return false return
end end
_G._outline_current_provider = provider return sidebar.provider[method](unpack(args))
if not provider.name then
_G._outline_current_provider.name = name
end
provider.request_symbols(on_symbols, opts)
return true
end end
return M return M

View File

@@ -89,4 +89,20 @@ function M.request_symbols(on_symbols, opts)
end) end)
end end
-- No good way to update outline when LSP action complete for now
---@param sidebar outline.Sidebar
function M.code_actions(sidebar)
sidebar:wrap_goto_location(function()
vim.lsp.buf.code_action()
end)
end
---@param sidebar outline.Sidebar
function M.rename_symbol(sidebar)
sidebar:wrap_goto_location(function()
vim.lsp.buf.rename()
end)
end
return M return M

View File

@@ -1,37 +0,0 @@
local outline = require('outline')
local M = {}
local function get_rename_params(node, winnr)
local bufnr = vim.api.nvim_win_get_buf(winnr)
local fn = 'file://' .. vim.api.nvim_buf_get_name(bufnr)
return {
textDocument = { uri = fn },
position = { line = node.line, character = node.character },
bufnr = bufnr,
}
end
function M.rename()
local current_line = vim.api.nvim_win_get_cursor(outline.current.view.winnr)[1]
local node = outline.current.flats[current_line]
local params = get_rename_params(node, outline.current.code.win)
local new_name = vim.fn.input({ prompt = 'New Name: ', default = node.name })
if not new_name or new_name == '' or new_name == node.name then
return
end
params.newName = new_name
vim.lsp.buf_request(params.bufnr, 'textDocument/rename', params, function(_, result, ctx)
if result ~= nil then
local client = vim.lsp.get_client_by_id(ctx.client_id)
vim.lsp.util.apply_workspace_edit(result, client.offset_encoding)
end
end)
end
return M

View File

@@ -23,6 +23,7 @@ local Sidebar = {}
---@field original_cursor string ---@field original_cursor string
---@field code outline.SidebarCodeState ---@field code outline.SidebarCodeState
---@field autocmds { [integer]: integer } winnr to autocmd id ---@field autocmds { [integer]: integer } winnr to autocmd id
---@field provider outline.Provider?
function Sidebar:new() function Sidebar:new()
return setmetatable({ return setmetatable({
@@ -50,6 +51,7 @@ function Sidebar:reset_state()
self.items = {} self.items = {}
self.flats = {} self.flats = {}
self.original_cursor = vim.o.guicursor self.original_cursor = vim.o.guicursor
self.provider = nil
self:delete_autocmds() self:delete_autocmds()
end end
@@ -62,6 +64,7 @@ function Sidebar:destroy()
self.items = nil self.items = nil
self.flats = nil self.flats = nil
self.code = nil self.code = nil
self.provider = nil
end end
---Handler for provider request_symbols when outline is opened for the first time. ---Handler for provider request_symbols when outline is opened for the first time.
@@ -135,8 +138,12 @@ function Sidebar:setup_keymaps()
up_and_jump = { '_move_and_jump', { 'up' } }, up_and_jump = { '_move_and_jump', { 'up' } },
hover_symbol = { require('outline.hover').show_hover, {} }, hover_symbol = { require('outline.hover').show_hover, {} },
toggle_preview = { require('outline.preview').toggle, {} }, toggle_preview = { require('outline.preview').toggle, {} },
rename_symbol = { require('outline.rename').rename, {} }, rename_symbol = {
code_actions = { require('outline.code_action').show_code_actions, {} }, providers.action, { self, 'rename_symbol', { self } }
},
code_actions = {
providers.action, { self, 'code_actions', { self } }
},
show_help = { require('outline.help').show_keymap_help, {} }, show_help = { require('outline.help').show_keymap_help, {} },
close = { function() self.view:close() end, {} }, close = { function() self.view:close() end, {} },
fold_toggle = { '_toggle_fold', {} }, fold_toggle = { '_toggle_fold', {} },
@@ -309,11 +316,16 @@ end
---Re-request symbols from provider ---Re-request symbols from provider
function Sidebar:__refresh() function Sidebar:__refresh()
local focused_outline = self.view.bufnr == vim.api.nvim_get_current_buf() local focused_outline = self.view.bufnr == vim.api.nvim_get_current_buf()
if self.view:is_open() and not focused_outline then if focused_outline or not self.view:is_open() then
providers.request_symbols(function(res) return
end
self.provider = providers.find_provider()
if not self.provider then
return
end
self.provider.request_symbols(function(res)
self:refresh_handler(res) self:refresh_handler(res)
end) end)
end
end end
-- stylua: ignore start -- stylua: ignore start
@@ -365,6 +377,17 @@ function Sidebar:_goto_and_close()
self:close() self:close()
end end
---Goto location in code, run fn() then go back to outline.
---Like emacs save-excursion but here it's explicitly goto_location.
---@param fn function
function Sidebar:wrap_goto_location(fn)
local pos = vim.api.nvim_win_get_cursor(0)
self:__goto_location(true)
fn()
vim.fn.win_gotoid(self.view.winnr)
vim.api.nvim_win_set_cursor(self.view.winnr, pos)
end
---@param direction "up"|"down" ---@param direction "up"|"down"
function Sidebar:_move_and_jump(direction) function Sidebar:_move_and_jump(direction)
local move = direction == 'down' and 1 or -1 local move = direction == 'down' and 1 or -1
@@ -494,12 +517,14 @@ function Sidebar:open(opts)
end end
if not self.view:is_open() then if not self.view:is_open() then
local found = providers.request_symbols(function(...) self.provider = providers.find_provider()
if not self.provider then
utils.echo('No providers found for current buffer')
return
end
self.provider.request_symbols(function(...)
self:initial_handler(...) self:initial_handler(...)
end, opts) end, opts)
if not found then
utils.echo('No providers found for current buffer')
end
end end
end end
@@ -558,7 +583,7 @@ end
---@return boolean has_provider ---@return boolean has_provider
function Sidebar:has_provider() function Sidebar:has_provider()
if self:has_focus() then if self:has_focus() then
return _G._outline_current_provider ~= nil return self.provider ~= nil
end end
return providers.has_provider() return providers.has_provider()
end end

View File

@@ -65,11 +65,13 @@
-- PROVIDER -- PROVIDER
---@class outline.Provider ---@class outline.Provider
---@field should_use_provider fun(bufnr:integer):boolean
---@field hover_info fun(bufnr:integer, params:table, on_info:function)
---@field request_symbols fun(on_symbols:function, opts:table)
---@field name string ---@field name string
---@field get_status? fun():string[] ---@field get_status? fun():string[]
---@field supports_buffer fun(bufnr:integer):boolean
---@field request_symbols fun(on_symbols:function, opts:table?)
---@field hover_info? fun(bufnr:integer, params:table, on_info:function)
---@field rename_symbol? fun(sidebar:outline.Sidebar)
---@field code_actions? fun(sidebar:outline.Sidebar)
-- HELP -- HELP