diff --git a/README.md b/README.md index 53664d833..2ed5d219d 100644 --- a/README.md +++ b/README.md @@ -372,9 +372,13 @@ Show go doc for api in neovim floating window. e.g. `GoDoc fmt.Println` If no argument provided, fallback to lsp.hover() +## GoDocBrowser + +Similar to GoDoc, but open the browser with the doc link. If no argument provided, open doc for current function/package + ## GoPkgOutline -A symbole outline for all symbols (var, const, func, struct, interface etc) inside a package You can still use navigator +A symbol outline for all symbols (var, const, func, struct, interface etc) inside a package You can still use navigator or sidebar plugins (e.g. vista, symbols-outline) to check outline within a file. But it is more useful for go to check the symbols in a package, as those symbols are visuals inside package, also the method can be defined in different source file. @@ -385,6 +389,11 @@ package If guihua not installed fallback to loclist image +## GoPkgSymbols + +A symbol outline for all symbols (var, const, func, struct, interface etc) inside current package +image + ## Modifytags Modify struct tags by [`gomodifytags`](https://github.com/fatih/gomodifytags) and treesitter diff --git a/doc/go.txt b/doc/go.txt index 71a5bac73..bc5dc2cb5 100644 --- a/doc/go.txt +++ b/doc/go.txt @@ -339,6 +339,10 @@ COMMANDS *go-nvim-commands* options: -f (floating win), -p package_name default options: sidepanel, current package in vim buffer +:GoPkgSymbols *:GoPkgSymbols* + show symbols inside current package in side panel/loclist + options: none + :GoImplements {options} *:GoImplements* GoImplements calls vim.lsp.buf.implementation diff --git a/lua/go/commands.lua b/lua/go/commands.lua index 0ea2e1cf3..71708fed1 100644 --- a/lua/go/commands.lua +++ b/lua/go/commands.lua @@ -247,6 +247,24 @@ return { nargs = '*', }) + create_cmd('GoPkgSymbols', function(opts) + require('go.package').symbols() + end, { + complete = function(a, l) + -- return package.loaded.go.package_complete(a, l) + return '' + end, + nargs = '*', + }) + create_cmd('GoGCDetails', function(opts) + require('go.gopls').gc_details(unpack(opts.fargs)) + end, { + complete = function(a, l) + return package.loaded.go.package_complete(a, l) + end, + nargs = '*', + }) + local lint_cfg = _GO_NVIM_CFG.golangci_lint or { default = 'standard' } local default = [[\ --default=]] .. lint_cfg.default local disable = lint_cfg.disable or {} diff --git a/lua/go/gopls.lua b/lua/go/gopls.lua index 2a5c82943..0af5e8055 100644 --- a/lua/go/gopls.lua +++ b/lua/go/gopls.lua @@ -113,6 +113,7 @@ for _, gopls_cmd in ipairs(gopls_cmds) do local gopls_cmd_name = string.sub(gopls_cmd, #'gopls.' + 1) cmds[gopls_cmd_name] = function(arg, callback) -- get gopls client + log(arg) local b = vim.api.nvim_get_current_buf() local clients = vim.lsp.get_clients({ bufnr = b }) @@ -135,8 +136,19 @@ for _, gopls_cmd in ipairs(gopls_cmds) do arguments[1].URIs = { uri } arguments[1].URI = nil end - arguments = { vim.tbl_extend('keep', arguments[1], arg or {}) } + local behavior = 'keep' + if arg.behavior then + behavior = arg.behavior + arg.behavior = nil + end + if behavior == 'replace' then + arg.behavior = nil + arguments = arg + else + arguments = { vim.tbl_extend(behavior, arguments[1], arg or {}) } + end + log('arguments', arguments) log(gopls_cmd_name, arguments) if vim.tbl_contains(gopls_with_result, gopls_cmd) then local resp = gopls.request_sync('workspace/executeCommand', { @@ -206,6 +218,18 @@ M.change_signature = function() cmds.change_signature(lsp_params) end +M.gc_details = function(args) + local uri = vim.uri_from_bufnr(0) + if args ~= nil then + args.URI = args[1] + end + local lsp_params = { + URI = args.URI, + behavior = 'replace', + } + cmds.gc_details(lsp_params) +end + M.list_imports = function(path) path = path or vim.fn.expand('%:p') local resp = cmds.list_imports({ @@ -242,8 +266,9 @@ M.list_pkgs = function() return pkgs end -M.package_symbols = function() - cmds.package_symbols() +M.package_symbols = function(pkg, render) + -- not sure how to add pkg info, leave it empty for now + cmds.package_symbols({}, render) end M.tidy = function() @@ -360,6 +385,7 @@ local function get_build_flags() return nil end end + local range_format = 'textDocument/rangeFormatting' local formatting = 'textDocument/formatting' -- https://cs.opensource.google/go/x/tools/+/master:gopls/internal/protocol/semtok/semtok.go diff --git a/lua/go/package.lua b/lua/go/package.lua index 409e345ef..8296dbac4 100644 --- a/lua/go/package.lua +++ b/lua/go/package.lua @@ -9,7 +9,7 @@ local pkgs = {} local complete = function(sep) log('complete', sep) sep = sep or '\n' - local ok, l = golist { util.all_pkgs() } + local ok, l = golist({ util.all_pkgs() }) if not ok then log('Failed to find all packages for current module/project.') return @@ -47,7 +47,7 @@ local complete = function(sep) end local all_pkgs = function() - local ok, l = golist { util.all_pkgs() } + local ok, l = golist({ util.all_pkgs() }) if not ok then log('Failed to find all packages for current module/project.') end @@ -160,47 +160,39 @@ local show_panel = function(result, pkg, rerender) end end - vim.lsp.buf_request( - 0, - 'workspace/symbol', - { query = "'" .. n.symbol }, - function(e, lsp_result, ctx) - local filtered = {} - for _, r in pairs(lsp_result) do - local container = r.containerName - if pkg == container and r.name == n.symbol then - table.insert(filtered, r) - end - end - log('filtered', filtered) - if #filtered == 0 then - log('nothing found fallback to result', pkg, n.symbol) - filtered = lsp_result + vim.lsp.buf_request(0, 'workspace/symbol', { query = "'" .. n.symbol }, function(e, lsp_result, ctx) + local filtered = {} + for _, r in pairs(lsp_result) do + local container = r.containerName + if pkg == container and r.name == n.symbol then + table.insert(filtered, r) end + end + log('filtered', filtered) + if #filtered == 0 then + log('nothing found fallback to result', pkg, n.symbol) + filtered = lsp_result + end - if vfn.empty(filtered) == 1 then - log(e, lsp_result, ctx) - vim.notify('no symbol found for ' .. vim.inspect(pkg)) - return false - end - if #filtered == 1 then - -- jump to pos - local loc = filtered[1].location - local buf = vim.uri_to_bufnr(loc.uri) - vfn.bufload(buf) - api.nvim_set_current_win(cur_win) - api.nvim_set_current_buf(buf) - api.nvim_win_set_buf(cur_win, buf) - api.nvim_win_set_cursor( - cur_win, - { loc.range.start.line + 1, loc.range.start.character } - ) - else - -- lets just call workspace/symbol handler - vim.lsp.handlers['workspace/symbol'](e, filtered, ctx) - end + if vfn.empty(filtered) == 1 then + log(e, lsp_result, ctx) + vim.notify('no symbol found for ' .. vim.inspect(pkg)) + return false end - ) + if #filtered == 1 then + -- jump to pos + local loc = filtered[1].location + local buf = vim.uri_to_bufnr(loc.uri) + vfn.bufload(buf) + api.nvim_set_current_win(cur_win) + api.nvim_set_current_buf(buf) + api.nvim_win_set_buf(cur_win, buf) + api.nvim_win_set_cursor(cur_win, { loc.range.start.line + 1, loc.range.start.character }) + else + -- lets just call workspace/symbol handler + vim.lsp.handlers['workspace/symbol'](e, filtered, ctx) + end + end) -- vim.lsp.buf.workspace_symbol("'" .. n.symbol) return n.symbol end, @@ -218,6 +210,73 @@ local show_panel = function(result, pkg, rerender) os.remove(fname) end +local show_pkg_panel = function(result, pkg, rerender) + local gopls = require('go.gopls') + gopls.package_symbols({}, function(result) + -- log('gopls package symbols', result) + if not result or vim.tbl_isempty(result) or vim.tbl_isempty(result.Symbols) then + vim.notify('no symbols found') + return + end + local files = result.Files + local items = {} + local kinds = require('guihua.lspkind').symbol_kind + for i = 1, #result.Symbols do + item = result.Symbols[i] + -- items[i].node_text = items[i].detail + item.uri =files[(item.file or 0) + 1] + item.filename = vim.uri_to_fname(item.uri) + item.kind = kinds(item.kind) + item.text = item.kind .. item.name + item.lnum = item.range.start.line + 1 + + table.insert(items, item) + if item.children then + local prefix = ' ┊ ' + for j = 1, #item.children do + -- if j == 1 then + -- prefix = ' 󱞩 ' + -- else + -- prefix = '  ' + -- end + local child = item.children[j] + child.lnum = child.range.start.line + 1 + child.uri = files[(child.file or 0) + 1] + child.filename = vim.uri_to_fname(child.uri) + child.kind = kinds(child.kind) + child.text = prefix .. child.kind .. child.name + table.insert(items, child) + end + end + end + log('gopls package symbols', items[1]) + log('gopls package symbols', items[2]) + log('gopls package symbols', items[3]) + + local panel = require('guihua.panel') + local log = require('guihua.log').info + local p = panel:new({ + header = '  󰏖 ' .. result.PackageName .. '  ', + render = function(bufnr) + log('render for ', bufnr) + return items + end, + -- override format function + -- format = function(item) + -- return item.indent .. '>' .. item.node_text + -- end + }) + log(p) + p:open(true) + end) +end + +local gopls_pkg_symbols = function() + local gopls = require('go.gopls') + +end + + local pkg_info = {} -- get package info local function handle_data_out(_, data, ev) @@ -283,6 +342,42 @@ local gen_pkg_info = function(cmd, pkg, arg, rerender) }) end +local function symbols_to_items(result) + local locations = {} + result = result or {} + log(#result) + for i = 1, #result do + local item = result[i].location + if item ~= nil and item.range ~= nil then + item.kind = result[i].kind + + local kind + item.name = result[i].name -- symbol name + item.text = result[i].name + if kind ~= nil then + item.text = kind .. ': ' .. item.text + end + if not item.filename then + item.filename = vim.uri_to_fname(item.uri) + end + item.display_filename = item.filename:gsub(cwd .. path_sep, path_cur, 1) + if item.range == nil or item.range.start == nil then + log('range not set', result[i], item) + end + item.lnum = item.range.start.line + 1 + + if item.containerName ~= nil then + item.text = ' ' .. item.containerName .. item.text + end + table.insert(locations, item) + end + end + -- log(locations[1]) + return locations +end + + + outline = function(...) -- log(debug.traceback()) local arg = select(1, ...) @@ -360,6 +455,7 @@ return { all_pkgs2 = all_pkgs2, pkg_from_path = pkg_from_path, outline = outline, + symbols = show_pkg_panel, } --[[