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:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
self:refresh_handler(res)
|
||||
end)
|
||||
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
|
||||
|
||||
-- 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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user