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()
local sidebar = M._get_sidebar(false)
local buf, win = 0, 0
local is_open
local is_open, provider
if sidebar then
buf = sidebar.code.buf
win = sidebar.code.win
is_open = sidebar.view:is_open()
provider = sidebar.provider
end
if not is_open then
provider = providers.find_provider()
end
---@type outline.StatusContext
local ctx = {
priority = cfg.o.providers.priority,
outline_open = is_open,
provider = provider,
}
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
local p = _G._outline_current_provider
if not is_open then
p = providers.find_provider()
end
if p ~= nil then
ctx.provider = p
if provider ~= nil then
-- Just show code window is active when the first outline in this tabpage
-- has not yet been opened.
if not sidebar then

View File

@@ -28,7 +28,7 @@ end
---@param result table
local function convert_symbols(result)
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
for _, value in pairs(result) do
value.children = {}

View File

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

View File

@@ -89,4 +89,20 @@ function M.request_symbols(on_symbols, opts)
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

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 code outline.SidebarCodeState
---@field autocmds { [integer]: integer } winnr to autocmd id
---@field provider outline.Provider?
function Sidebar:new()
return setmetatable({
@@ -50,6 +51,7 @@ function Sidebar:reset_state()
self.items = {}
self.flats = {}
self.original_cursor = vim.o.guicursor
self.provider = nil
self:delete_autocmds()
end
@@ -62,6 +64,7 @@ function Sidebar:destroy()
self.items = nil
self.flats = nil
self.code = nil
self.provider = nil
end
---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' } },
hover_symbol = { require('outline.hover').show_hover, {} },
toggle_preview = { require('outline.preview').toggle, {} },
rename_symbol = { require('outline.rename').rename, {} },
code_actions = { require('outline.code_action').show_code_actions, {} },
rename_symbol = {
providers.action, { self, 'rename_symbol', { self } }
},
code_actions = {
providers.action, { self, 'code_actions', { self } }
},
show_help = { require('outline.help').show_keymap_help, {} },
close = { function() self.view:close() end, {} },
fold_toggle = { '_toggle_fold', {} },
@@ -309,11 +316,16 @@ end
---Re-request symbols from provider
function Sidebar:__refresh()
local focused_outline = self.view.bufnr == vim.api.nvim_get_current_buf()
if self.view:is_open() and not focused_outline then
providers.request_symbols(function(res)
if focused_outline or not self.view:is_open() then
return
end
self.provider = providers.find_provider()
if not self.provider then
return
end
self.provider.request_symbols(function(res)
self:refresh_handler(res)
end)
end
end
-- stylua: ignore start
@@ -365,6 +377,17 @@ function Sidebar:_goto_and_close()
self:close()
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"
function Sidebar:_move_and_jump(direction)
local move = direction == 'down' and 1 or -1
@@ -494,12 +517,14 @@ function Sidebar:open(opts)
end
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(...)
end, opts)
if not found then
utils.echo('No providers found for current buffer')
end
end
end
@@ -558,7 +583,7 @@ end
---@return boolean has_provider
function Sidebar:has_provider()
if self:has_focus() then
return _G._outline_current_provider ~= nil
return self.provider ~= nil
end
return providers.has_provider()
end

View File

@@ -65,11 +65,13 @@
-- 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 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