go.nvim/lua/go/impl.lua

187 lines
5.0 KiB
Lua
Raw Normal View History

2021-07-14 15:35:38 +00:00
-- local ts_utils = require 'nvim-treesitter.ts_utils'
2022-12-14 20:11:08 +00:00
local utils = require('go.utils')
local log = utils.log
2022-06-01 11:29:13 +00:00
local vfn = vim.fn
2022-12-14 20:11:08 +00:00
local impl = 'impl' -- GoImpl f *Foo io.Writer
2021-12-22 04:01:15 +00:00
-- use ts to get name
local function get_type_name()
2022-12-14 20:11:08 +00:00
local name = require('go.ts.go').get_struct_node_at_pos()
2021-12-22 04:01:15 +00:00
if name == nil then
2022-12-14 20:11:08 +00:00
name = require('go.ts.go').get_type_node_at_pos()
2021-12-22 04:01:15 +00:00
end
utils.log(name)
if name == nil then
2022-12-14 20:11:08 +00:00
return ''
end
local node_name = name.name
-- let move the cursor to end of line of struct name
local dim = name.dim.e
-- let move cursor
local r, c = dim.r, dim.c
2022-12-14 20:11:08 +00:00
utils.log('move cusror to ', r, c)
vim.api.nvim_win_set_cursor(0, { r, c })
2022-05-21 05:11:10 +00:00
return node_name
2021-12-22 04:01:15 +00:00
end
local function get_interface_name()
2022-12-14 20:11:08 +00:00
local name = require('go.ts.go').get_interface_node_at_pos()
utils.log(name)
if name == nil then
return nil
end
local node_name = name.name
-- let move the cursor to end of line of struct name
local dim = name.dim.e
-- let move cursor
local r, c = dim.r, dim.c
2022-12-14 20:11:08 +00:00
utils.log('move cusror to ', r, c)
vim.api.nvim_win_set_cursor(0, { r, c })
2022-12-14 20:11:08 +00:00
local pkg = require('go.package').pkg_from_path(nil, vim.api.nvim_get_current_buf())
log(pkg[1])
if pkg then
2022-12-14 20:11:08 +00:00
return pkg[1] .. '.' .. node_name
end
end
2021-07-14 15:35:38 +00:00
local run = function(...)
2022-12-14 20:11:08 +00:00
require('go.install').install(impl)
local impl_cmd = 'impl'
local iface = ''
local recv_name = ''
2021-12-22 04:01:15 +00:00
local arg = { ... }
utils.log(#arg, arg)
2021-12-22 04:01:15 +00:00
local recv = get_type_name()
2022-07-26 16:21:58 +00:00
iface = get_interface_name()
2022-05-21 05:11:10 +00:00
if #arg == 0 then
2022-12-14 20:11:08 +00:00
if not iface then
iface = vfn.input('Impl: generating method stubs for interface: ')
end
vim.cmd('redraw!')
if iface == '' then
utils.notify('Impl: please input interface name e.g. io.Reader or receiver name e.g. GoImpl MyType')
-- print("Usage: GoImpl f *File io.Reader")
2021-12-22 04:01:15 +00:00
end
elseif #arg == 1 then
-- " i.e: ':GoImpl io.Writer'
if iface ~= nil then
recv = select(1, ...)
2022-12-14 20:11:08 +00:00
recv = string.lower(recv) .. ' *' .. recv
else
2022-12-14 20:11:08 +00:00
recv = string.lower(recv) .. ' *' .. recv
iface = select(1, ...)
end
2022-12-14 20:11:08 +00:00
if recv == '' and iface == '' then
vim.notify('put cursor on struct or a interface or specify a receiver & interface')
end
2022-05-21 05:11:10 +00:00
utils.log(recv)
2022-12-14 20:11:08 +00:00
vim.cmd('redraw!')
elseif #arg == 2 then
utils.log(recv)
if iface ~= nil then
-- " i.e: ':GoImpl s TypeName'
recv = select(1, ...)
2022-07-26 16:21:58 +00:00
local recv_type = select(2, ...)
2022-12-14 20:11:08 +00:00
recv = string.lower(recv) .. ' *' .. recv_type
else
recv_name = select(1, ...)
2022-12-14 20:11:08 +00:00
recv = string.format('%s *%s', recv_name, recv)
local l = #arg
iface = select(l, ...)
end
2021-12-22 04:01:15 +00:00
elseif #arg > 2 then
local l = #arg
iface = select(l, ...)
recv = select(l - 1, ...)
2022-05-21 05:11:10 +00:00
recv_name = select(l - 2, ...)
2022-12-14 20:11:08 +00:00
recv = string.format('%s %s', recv_name, recv)
2021-07-14 15:35:38 +00:00
end
2022-05-21 05:11:10 +00:00
utils.log(#arg, recv_name, recv, iface)
2022-12-14 20:11:08 +00:00
local dir = vfn.fnameescape(vfn.expand('%:p:h'))
2021-12-22 04:01:15 +00:00
2022-12-14 20:11:08 +00:00
impl_cmd = { impl_cmd, '-dir', dir, recv, iface }
utils.log(impl_cmd)
-- vim.cmd("normal! $%") -- do a bracket match. changed to treesitter
local opts = {
update_buffer = true,
on_exit = function(code, signal, data)
if code ~= 0 or signal ~= 0 then
2022-12-14 20:11:08 +00:00
utils.warn('impl failed' .. vim.inspect(data))
return
end
2022-12-14 20:11:08 +00:00
data = vim.split(data, '\n')
data = utils.handle_job_data(data)
if not data then
return
end
vim.schedule(function()
2022-12-14 20:11:08 +00:00
local lnum = vfn.getcurpos()[2]
table.insert(data, 1, '')
vfn.append(lnum, data)
vim.cmd('w')
end)
end,
}
2022-12-14 20:11:08 +00:00
local runner = require('go.runner')
opts.sprite_enable = false
runner.run(impl_cmd, opts)
2021-12-22 04:01:15 +00:00
end
local function match_iface_name(part)
2022-12-14 20:11:08 +00:00
local pkg, iface = string.match(part, '^(.*)%.(.*)$')
2021-07-14 15:35:38 +00:00
2021-12-22 04:01:15 +00:00
utils.log(pkg, iface)
2022-12-14 20:11:08 +00:00
local cmd = string.format('go doc %s', pkg)
2022-06-01 11:29:13 +00:00
local doc = vfn.systemlist(cmd)
2021-12-22 04:01:15 +00:00
if vim.v.shell_error ~= 0 then
2022-12-14 20:11:08 +00:00
utils.warn('go doc failed' .. vim.inspect(doc))
2021-12-22 04:01:15 +00:00
return
end
local ifaces = {}
2022-12-14 20:11:08 +00:00
local pat = string.format('^type (%s.*) interface', iface)
2021-12-22 04:01:15 +00:00
for _, line in ipairs(doc) do
local m = string.match(line, pat)
if m ~= nil then
2022-12-14 20:11:08 +00:00
table.insert(ifaces, string.format('%s.%s', pkg, m))
2021-12-22 04:01:15 +00:00
end
end
return ifaces
end
2022-06-01 11:29:13 +00:00
-- function complete(arglead, cmdline, cursorpos)
local function complete(_, cmdline, _)
2021-12-22 04:01:15 +00:00
local words = vim.split(cmdline, [[%s+]])
2022-12-14 20:11:08 +00:00
local gopls = require('go.gopls')
2021-12-22 04:01:15 +00:00
local last = words[#words]
local iface = get_interface_name()
2022-12-14 20:11:08 +00:00
local query = require('go.ts.go').query_type_declaration
local bufnr = vim.api.nvim_get_current_buf()
if iface ~= nil then
2022-12-14 20:11:08 +00:00
local nodes = require('go.ts.nodes').nodes_in_buf(query, 'go', nil, bufnr, 100000, 100000)
local ns = {}
log(nodes)
for _, node in ipairs(nodes) do
table.insert(ns, node.name)
end
log(ns)
return vfn.uniq(ns)
end
2022-12-14 20:11:08 +00:00
if string.match(last, '^.+%..*') ~= nil then
2021-12-22 04:01:15 +00:00
local part = match_iface_name(last)
if part ~= nil then
return part
end
end
2022-06-01 11:29:13 +00:00
return vfn.uniq(vfn.sort(gopls.list_pkgs()))
2021-07-14 15:35:38 +00:00
end
2021-12-22 04:01:15 +00:00
return { run = run, complete = complete }