mirror of https://github.com/ray-x/go.nvim
init commit
commit
1e190d6a0e
@ -0,0 +1,92 @@
|
|||||||
|
# [WIP] go.nvim
|
||||||
|
|
||||||
|
A modern golang neovim plugin based on treesitter and nvim-lsp. Written in Lua. Async as much as possible.
|
||||||
|
PR & Suggestions welcome
|
||||||
|
|
||||||
|
## install
|
||||||
|
|
||||||
|
add 'ray-x/go.nvim' to your package manager
|
||||||
|
related binaries will be installed the first time you using it
|
||||||
|
Add lsp format in your vimrc. You can check my dotfiles for details
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require('go').setup()
|
||||||
|
```
|
||||||
|
|
||||||
|
## code format
|
||||||
|
|
||||||
|
nvim-lsp support goimport by default.
|
||||||
|
```vim
|
||||||
|
autocmd BufWritePre (InsertLeave?) <buffer> lua vim.lsp.buf.formatting_sync(nil,500)
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin provides code format, by default is goline + gofumports (stricter version of goimport)
|
||||||
|
|
||||||
|
The format tool is a asyn format tool in format.lua
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("go.format").gofmt()
|
||||||
|
require("go.format").goimport()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Textobject
|
||||||
|
|
||||||
|
Supported by treesitter. TS provided better parse result compared to regular expression.
|
||||||
|
|
||||||
|
## Build and test
|
||||||
|
|
||||||
|
Provided wrapper for gobulild/test etc
|
||||||
|
|
||||||
|
## unit test with gotests
|
||||||
|
|
||||||
|
Support table based unit test auto generate, parse current function/method name using treesitter
|
||||||
|
|
||||||
|
## Modifytags
|
||||||
|
|
||||||
|
modifytags by `modifytags` and treesitter
|
||||||
|
|
||||||
|
## GoFmt
|
||||||
|
|
||||||
|
nvim-lsp support goimport by default. The plugin provided a new formatter, goline + gofumports (stricter version of
|
||||||
|
goimport)
|
||||||
|
|
||||||
|
## Comments and Doc
|
||||||
|
|
||||||
|
Auto doc (to suppress golang-lint warning), generate comments by treesitter parsing result
|
||||||
|
|
||||||
|
```go
|
||||||
|
type GoLintComplaining struct{}
|
||||||
|
```
|
||||||
|
```lua
|
||||||
|
lua.require('go.comment').add_comment() -- or your faviourite key binding and setup placeholder "no more complaint ;P"
|
||||||
|
```
|
||||||
|
The code will be:
|
||||||
|
```go
|
||||||
|
// GoLintComplaining struct no more complaint ;P
|
||||||
|
type GoLintComplaining struct{}
|
||||||
|
```
|
||||||
|
|
||||||
|
## LSP
|
||||||
|
|
||||||
|
LSP supported by nvim-lsp is good enough for a gopher. If you looking for a better GUI. lspsaga and lsp-utils are
|
||||||
|
what you are looking for.
|
||||||
|
|
||||||
|
## Lint
|
||||||
|
|
||||||
|
Supported by LSP, if you need golangci-lint better with ALE
|
||||||
|
|
||||||
|
## configuration
|
||||||
|
|
||||||
|
lua suggested:
|
||||||
|
```lua
|
||||||
|
require('go').setup(cfg = {
|
||||||
|
goimport='gofumports', -- g:go_nvim_goimport
|
||||||
|
gofmt = 'gofumpt', --g:go_nvim_gofmt,
|
||||||
|
max_len = 100, -- g:go_nvim_max_len
|
||||||
|
transform = false, -- vim.g.go_nvim_tag_transfer check gomodifytags for details
|
||||||
|
test_template = '', -- default to testify if not set; g:go_nvim_tests_template check gotests for details
|
||||||
|
test_template_dir = '', -- default to nil if not set; g:go_nvim_tests_template_dir check gotests for details
|
||||||
|
comment_placeholder = '' , -- vim.g.go_nvim_comment_placeholder your cool placeholder e.g. ﳑ
|
||||||
|
verbose = false, -- output loginf in messages
|
||||||
|
})
|
||||||
|
```
|
@ -0,0 +1,5 @@
|
|||||||
|
goimport not stable (failed on 2nd time from time to time)
|
||||||
|
gomodifytags
|
||||||
|
goimport: could not import.... auto import by run 'go get' "not in your go.mod" append to gomod
|
||||||
|
key mappings/nvim commands
|
||||||
|
GoTests -- add unit test
|
@ -0,0 +1,39 @@
|
|||||||
|
-- some of commands extracted from gopher.vim
|
||||||
|
|
||||||
|
local go = {}
|
||||||
|
|
||||||
|
function go.setup(cfg)
|
||||||
|
vim.g.go_nvim_goimport = cfg.goimport or 'gofumports' -- g:go_nvim_goimport
|
||||||
|
vim.g.go_nvim_gofmt = cfg.gofmt or 'gofumpt' --g:go_nvim_gofmt,
|
||||||
|
vim.g.go_nvim_max_len = cfg.max_len or 100 -- g:go_nvim_max_len
|
||||||
|
vim.g.go_nvim_transform = cfg.transform or false -- vim.g.go_nvim_tag_transfer check gomodifytags for details
|
||||||
|
vim.g.go_nvim_test_dir = cfg.test_dir or '' -- default to current dir. g:go_nvim_tests_dir check gotests for details
|
||||||
|
vim.g.go_nvim_comment_placeholder = cfg.comment_placeholder or ' ' -- vim.g.go_nvim_comment_placeholder your cool placeholder e.g. ﳑ
|
||||||
|
vim.g.go_nvim_verbose = cfg.verbose or false -- output loginf in messages
|
||||||
|
|
||||||
|
|
||||||
|
vim.cmd('command Gofmt lua require("go.format").gofmt()')
|
||||||
|
vim.cmd('command Goimport lua require("go.format").goimport()')
|
||||||
|
|
||||||
|
vim.cmd([[command GoBuild :setl makeprg=go\ build | :make]])
|
||||||
|
vim.cmd([[command GoGenerate :setl makeprg=go\ generate | :make]])
|
||||||
|
vim.cmd([[command GoRun :setl makeprg=go\ run | :make]])
|
||||||
|
vim.cmd([[command GoTestFunc :make -run ..]])
|
||||||
|
|
||||||
|
vim.cmd([[command GoTest :compiler gotest | :make]])
|
||||||
|
vim.cmd([[command GoTestCompile setl makeprg=go\ build | :make]])
|
||||||
|
vim.cmd([[command GoTest setl makeprg=go\ build | :make]])
|
||||||
|
|
||||||
|
|
||||||
|
vim.cmd([[command GoAddTest lua require("go.gotests").fun_test()]])
|
||||||
|
vim.cmd([[command GoAddExpTest lua require("go.gotests").exported_test()]])
|
||||||
|
vim.cmd([[command GoAddAllTest lua require("go.gotests").all_test()]])
|
||||||
|
|
||||||
|
vim.cmd([[command! -nargs=* GoAddTag lua require("go.tags").add(<f-args>)]])
|
||||||
|
vim.cmd([[command! -nargs=* GoRmTag lua require("go.tags").rm(<f-args>)]])
|
||||||
|
vim.cmd([[command GoClearTag lua require("go.tags").clear()]])
|
||||||
|
|
||||||
|
vim.cmd([[command GoLint :compiler golangci-lint | :make]])
|
||||||
|
|
||||||
|
end
|
||||||
|
return go
|
@ -0,0 +1,64 @@
|
|||||||
|
-- todo
|
||||||
|
-- for func name(args) rets {}
|
||||||
|
-- add cmts // name : rets
|
||||||
|
local comment = {}
|
||||||
|
local placeholder = vim.g.go_nvim_comment_placeholder or ""
|
||||||
|
local ulog = require "go.utils".log
|
||||||
|
local gen_comment = function(row, col)
|
||||||
|
local comments = nil
|
||||||
|
|
||||||
|
local ns = require("go.ts.go").get_package_node_at_pos(row, col)
|
||||||
|
if ns ~= nil and ns ~= {} then
|
||||||
|
-- utils.log("parnode" .. vim.inspect(ns))
|
||||||
|
comments = "// Package " .. ns.name .. " provides " .. ns.name
|
||||||
|
return comments, ns
|
||||||
|
end
|
||||||
|
ns = require("go.ts.go").get_func_method_node_at_pos(row, col)
|
||||||
|
if ns ~= nil and ns ~= {} then
|
||||||
|
-- utils.log("parnode" .. vim.inspect(ns))
|
||||||
|
comments = "// " .. ns.name .. " " .. ns.type
|
||||||
|
return comments, ns
|
||||||
|
end
|
||||||
|
ns = require("go.ts.go").get_struct_node_at_pos(row, col)
|
||||||
|
if ns ~= nil and ns ~= {} then
|
||||||
|
comments = "// " .. ns.name .. " " .. ns.type
|
||||||
|
return comments, ns
|
||||||
|
end
|
||||||
|
ns = require("go.ts.go").get_interface_node_at_pos(row, col)
|
||||||
|
if ns ~= nil and ns ~= {} then
|
||||||
|
-- utils.log("parnode" .. vim.inspect(ns))
|
||||||
|
comments = "// " .. ns.name .. " " .. ns.type
|
||||||
|
return comments, ns
|
||||||
|
end
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local wrap_comment = function(comment_line, ns)
|
||||||
|
if string.len(comment_line)>0 and placeholder ~= nil and string.len(placeholder)>0 then
|
||||||
|
return comment_line .. " " .. placeholder, ns
|
||||||
|
end
|
||||||
|
return comment_line, ns
|
||||||
|
end
|
||||||
|
|
||||||
|
comment.gen = function(row, col)
|
||||||
|
if row == nil or col == nil then
|
||||||
|
row, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||||
|
row, col = row + 1, col + 1
|
||||||
|
end
|
||||||
|
local c, ns = wrap_comment(gen_comment(row, col))
|
||||||
|
--ulog(vim.inspect(ns))
|
||||||
|
row, col = ns.dim.s.r, ns.dim.s.c
|
||||||
|
ulog("set cursor " .. tostring(row))
|
||||||
|
vim.api.nvim_win_set_cursor(0, {row, col})
|
||||||
|
-- insert doc
|
||||||
|
vim.fn.append(row - 1, c)
|
||||||
|
-- set curosr
|
||||||
|
vim.fn.cursor(row, #c+1)
|
||||||
|
-- enter into insert mode
|
||||||
|
vim.api.nvim_command('startinsert!')
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return comment
|
@ -0,0 +1,78 @@
|
|||||||
|
-- golines A golang formatter that fixes long lines
|
||||||
|
-- golines + gofumports(stricter gofmt + goimport)
|
||||||
|
local api = vim.api
|
||||||
|
local util = require("go.utils")
|
||||||
|
local max_len = vim.g.go_nvim_max_len and vim.g.go_nvim_max_len or 100
|
||||||
|
local goimport = vim.g.go_nvim_goimport ~= nil and vim.g.go_nvim_goimport or "gofumports"
|
||||||
|
local gofmt = vim.g.go_nvim_gofmt ~= nil and vim.g.go_nvim_gofmt or "gofumpt"
|
||||||
|
local gofmt_args =
|
||||||
|
vim.g.go_nvim_gofmt_args and vim.g.go_nvim_gofmt_args or
|
||||||
|
{"--max-len=" .. tostring(max_len), "--base-formatter=" .. gofmt}
|
||||||
|
local utils = require('go').utils
|
||||||
|
|
||||||
|
local goimport_args =
|
||||||
|
vim.g.go_nvim_goimport_args and vim.g.go_nvim_goimport_args or
|
||||||
|
{"--max-len=" .. tostring(max_len), "--base-formatter=" .. goimport}
|
||||||
|
|
||||||
|
local run = function(args, from_buffer)
|
||||||
|
if not from_buffer then
|
||||||
|
table.insert(args, api.nvim_buf_get_name(0))
|
||||||
|
print('formatting... ' .. api.nvim_buf_get_name(0) .. vim.inspect(args))
|
||||||
|
end
|
||||||
|
|
||||||
|
local old_lines = api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
table.insert(args, 1, "golines")
|
||||||
|
|
||||||
|
local j =
|
||||||
|
vim.fn.jobstart(
|
||||||
|
args,
|
||||||
|
{
|
||||||
|
on_stdout = function(job_id, data, event)
|
||||||
|
if not data or #data==1 and data[1] == "" then return end
|
||||||
|
if not util.check_same(old_lines, data) then
|
||||||
|
print("updating codes")
|
||||||
|
api.nvim_buf_set_lines(0, 0, #data, false, data)
|
||||||
|
api.nvim_command("write")
|
||||||
|
else
|
||||||
|
print("already formatted")
|
||||||
|
end
|
||||||
|
utils.log("stdout" .. vim.inspect(data))
|
||||||
|
old_lines = nil
|
||||||
|
|
||||||
|
end,
|
||||||
|
on_stderr = function(job_id, data, event)
|
||||||
|
print(vim.inspect(data) .. "stderr")
|
||||||
|
end,
|
||||||
|
on_exit = function(id, data, event)
|
||||||
|
-- utils.log(vim.inspect(data) .. "exit")
|
||||||
|
-- utils.log("current data " .. vim.inspect(new_lines))
|
||||||
|
old_lines = nil
|
||||||
|
end,
|
||||||
|
stdout_buffered = true,
|
||||||
|
stderr_buffered = true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
vim.fn.chansend(j, old_lines)
|
||||||
|
vim.fn.chanclose(j, "stdin")
|
||||||
|
end
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
M.gofmt = function(buf)
|
||||||
|
vim.env.GO_TEST = "gofmt"
|
||||||
|
buf = buf or false
|
||||||
|
require("go.install").install(gofmt)
|
||||||
|
require("go.install").install("golines")
|
||||||
|
local a = {}
|
||||||
|
util.copy_array(gofmt_args, a)
|
||||||
|
run(a, buf)
|
||||||
|
end
|
||||||
|
|
||||||
|
M.goimport = function()
|
||||||
|
buf = buf or false
|
||||||
|
require("go.install").install(goimport)
|
||||||
|
require("go.install").install("golines")
|
||||||
|
local a = {}
|
||||||
|
util.copy_array(goimport_args, a)
|
||||||
|
run(a, buf)
|
||||||
|
end
|
||||||
|
return M
|
@ -0,0 +1,85 @@
|
|||||||
|
-- Table driven tests based on its target source files' function and method signatures.
|
||||||
|
-- https://github.com/cweill/gotests
|
||||||
|
local ut = {}
|
||||||
|
local gotests = "gotests"
|
||||||
|
local test_dir = vim.g.go_nvim_test_dir or ""
|
||||||
|
local test_template = vim.go_nvim_test_template or ""
|
||||||
|
local utils = require("go").utils
|
||||||
|
local run = function(setup)
|
||||||
|
print(vim.inspect(setup))
|
||||||
|
local j =
|
||||||
|
vim.fn.jobstart(
|
||||||
|
setup,
|
||||||
|
{
|
||||||
|
on_stdout = function(jobid, data, event)
|
||||||
|
print("unit tests generate " .. vim.inspect(data))
|
||||||
|
end,
|
||||||
|
on_stderr = function(_, data, _)
|
||||||
|
print("failed to generate tests for " .. vim.inspect(setup) .. "error: " .. vim.inspect(data))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local add_test = function(args)
|
||||||
|
require("go.install").install(gotests)
|
||||||
|
if string.len(test_template) > 1 then
|
||||||
|
table.insert(args, "-template")
|
||||||
|
table.insert(args, test_template)
|
||||||
|
if string.len(test_dir) > 1 then
|
||||||
|
table.insert(args, "-template_dir")
|
||||||
|
table.insert(args, test_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||||
|
row, col = row + 1, col + 1
|
||||||
|
local ns = require("go.ts.go").get_func_method_node_at_pos(row, col)
|
||||||
|
if ns == nil or ns == {} then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
utils.log("parnode" .. vim.inspect(ns))
|
||||||
|
run(args)
|
||||||
|
end
|
||||||
|
|
||||||
|
ut.fun_test = function(parallel)
|
||||||
|
parallel = parallel or false
|
||||||
|
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||||
|
row, col = row + 1, col + 1
|
||||||
|
local ns = require("go.ts.go").get_func_method_node_at_pos(row, col)
|
||||||
|
if ns == nil or ns == {} then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- utils.log("parnode" .. vim.inspect(ns))
|
||||||
|
local funame = ns.name
|
||||||
|
-- local rs, re = ns.dim.s.r, ns.dim.e.r
|
||||||
|
local gofile = vim.fn.expand("%")
|
||||||
|
local args = {gotests, "-w", "-only", funame, gofile}
|
||||||
|
if parallel then
|
||||||
|
table.insert(args, "-parallel")
|
||||||
|
end
|
||||||
|
add_test(args)
|
||||||
|
end
|
||||||
|
|
||||||
|
ut.all_test = function(parallel)
|
||||||
|
parallel = parallel or false
|
||||||
|
local gofile = vim.fn.expand("%")
|
||||||
|
local args = {gotests, "-all", "-w", gofile}
|
||||||
|
if parallel then
|
||||||
|
table.insert(args, "-parallel")
|
||||||
|
end
|
||||||
|
add_test(args)
|
||||||
|
end
|
||||||
|
|
||||||
|
ut.exported_test = function(parallel)
|
||||||
|
parallel = parallel or false
|
||||||
|
local gofile = vim.fn.expand("%")
|
||||||
|
local args = {gotests, "-exported", "-w", gofile}
|
||||||
|
if parallel then
|
||||||
|
table.insert(args, "-parallel")
|
||||||
|
end
|
||||||
|
add_test(args)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ut
|
@ -0,0 +1,61 @@
|
|||||||
|
local uv = vim.loop
|
||||||
|
local gopath = vim.fn.expand("$GOPATH")
|
||||||
|
local gobinpath = gopath .. "/bin/"
|
||||||
|
local url = {
|
||||||
|
golines = "segmentio/golines",
|
||||||
|
gofumpt = "mvdan/gofumpt",
|
||||||
|
gofumports = "mvdan/gofumpt",
|
||||||
|
gomodifytags = "fatih/gomodifytags",
|
||||||
|
gotsts = "cweill/gotests",
|
||||||
|
}
|
||||||
|
|
||||||
|
local function install(bin)
|
||||||
|
local state = uv.fs_stat(gobinpath .. bin)
|
||||||
|
if not state then
|
||||||
|
print("installing " .. bin)
|
||||||
|
local u = url[bin]
|
||||||
|
if u == nil then
|
||||||
|
print("command " .. bin .. " not supported, please update install.lua")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local setup = {
|
||||||
|
"go", "get",
|
||||||
|
u
|
||||||
|
}
|
||||||
|
vim.fn.jobstart(
|
||||||
|
setup,
|
||||||
|
-- setup.args,
|
||||||
|
{
|
||||||
|
on_stdout = function(c, data, name)
|
||||||
|
print(data)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update(bin)
|
||||||
|
local u = url[bin]
|
||||||
|
if u == nil then
|
||||||
|
print("command " .. bin .. " not supported, please update install.lua")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local setup = {"go", "get", "-u", u}
|
||||||
|
|
||||||
|
vim.fn.jobstart(
|
||||||
|
setup,
|
||||||
|
{
|
||||||
|
on_stdout = function(c, data, name)
|
||||||
|
print(data)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function install_all()
|
||||||
|
for key, value in pairs(url) do
|
||||||
|
install(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {install = install, update = update, install_all = install_all}
|
@ -0,0 +1,65 @@
|
|||||||
|
local uv, api = vim.loop, vim.api
|
||||||
|
|
||||||
|
local check_same = function(tbl1, tbl2)
|
||||||
|
if #tbl1 ~= #tbl2 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for k, v in ipairs(tbl1) do
|
||||||
|
if v ~= tbl2[k] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local run = function(cmd, args, on_stdout, stdin_data, buf)
|
||||||
|
buf = buf or false
|
||||||
|
local stdin = uv.new_pipe(false)
|
||||||
|
local stdout = uv.new_pipe(false)
|
||||||
|
local stderr = uv.new_pipe(false)
|
||||||
|
local file = api.nvim_buf_get_name(0)
|
||||||
|
local handle, pid =
|
||||||
|
uv.spawn(
|
||||||
|
cmd,
|
||||||
|
{
|
||||||
|
stdio = {stdin, stdout, stderr},
|
||||||
|
args = args
|
||||||
|
},
|
||||||
|
function(code, signal) -- on exit
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
uv.read_start(stdout, vim.schedule_wrap(on_stdout))
|
||||||
|
|
||||||
|
uv.read_start(
|
||||||
|
stderr,
|
||||||
|
function(err, data)
|
||||||
|
assert(not err, err)
|
||||||
|
if data then
|
||||||
|
print("stderr chunk", stderr, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
if buf then
|
||||||
|
for i = 1, #stdin_data do
|
||||||
|
print("sending " .. stdin_data[i])
|
||||||
|
stdin:write(stdin_data[i])
|
||||||
|
end
|
||||||
|
if not stdin:is_closing() then
|
||||||
|
stdin:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
uv.shutdown(
|
||||||
|
stdin,
|
||||||
|
function()
|
||||||
|
uv.close(
|
||||||
|
handle,
|
||||||
|
function()
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {golines_format = golines_format, run = run}
|
@ -0,0 +1,86 @@
|
|||||||
|
local tags = {}
|
||||||
|
-- support -add-tags, --add-options, -remove-tags, -remove-options, clear-tags, clear-options
|
||||||
|
-- for struct and line range
|
||||||
|
-- gomodifytags -file demo.go -struct Server -add-tags json
|
||||||
|
-- gomodifytags -file demo.go -struct Server -add-tags json -w
|
||||||
|
-- gomodifytags -file demo.go -struct Server -add-tags json,xml
|
||||||
|
-- gomodifytags -file demo.go -struct Server -add-tags json,xml -transform camelcase
|
||||||
|
-- gomodifytags -file demo.go -line 8,11 -clear-tags xml
|
||||||
|
|
||||||
|
local opts = {"-add-tags", "-add-options", "-remove-tags", "-remove-options", "-clear-tags", "-clear-options"}
|
||||||
|
local gomodify = "gomodifytags"
|
||||||
|
local transform = vim.g.go_nvim_tag_transfer
|
||||||
|
tags.modify = function(...)
|
||||||
|
require("go.install").install(gomodify)
|
||||||
|
local fname = vim.fn.expand("%") -- %:p:h ? %:p
|
||||||
|
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||||
|
row, col = row + 1, col + 1
|
||||||
|
local ns = require("go.ts.go").get_struct_node_at_pos(row, col)
|
||||||
|
if ns == nil or ns == {} then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- print("parnode" .. vim.inspect(ns))
|
||||||
|
local struct_name = ns.name
|
||||||
|
local rs, re = ns.dim.s.r, ns.dim.e.r
|
||||||
|
setup = {gomodify, "-format", "json", "-file", fname, "-struct", struct_name, '-w'}
|
||||||
|
if transform ~= nil then
|
||||||
|
table.insert(setup.args, "-transform")
|
||||||
|
table.insert(setup.args, transform)
|
||||||
|
end
|
||||||
|
local arg = {...}
|
||||||
|
for i, v in ipairs(arg) do
|
||||||
|
table.insert(setup, v)
|
||||||
|
end
|
||||||
|
|
||||||
|
if #arg == 1 and arg[1] ~= "clear-tags" then
|
||||||
|
table.insert(setup, "json")
|
||||||
|
end
|
||||||
|
-- print(vim.inspect(setup))
|
||||||
|
local j =
|
||||||
|
vim.fn.jobstart(
|
||||||
|
setup,
|
||||||
|
{
|
||||||
|
on_stdout = function(jobid, data, event)
|
||||||
|
if not data or #data == 1 and data[1] == "" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local tagged = vim.fn.json_decode(data)
|
||||||
|
-- print(vim.inspect(tagged))
|
||||||
|
-- print(tagged["start"], tagged["end"], tagged.lines)
|
||||||
|
if tagged.errors ~= nil or tagged.lines == nil or tagged["start"] == nil or tagged["start"] == 0 then
|
||||||
|
print("failed to set tags" .. vim.inspect(tagged))
|
||||||
|
end
|
||||||
|
vim.api.nvim_buf_set_lines(0, tagged["start"]-1, tagged["start"]-1+#tagged.lines, false, tagged.lines)
|
||||||
|
vim.cmd("write")
|
||||||
|
print("wrote " .. tostring(tagged.lines))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
tags.add = function(...)
|
||||||
|
local cmd = {"-add-tags"}
|
||||||
|
local arg = {...}
|
||||||
|
for _, v in ipairs(arg) do
|
||||||
|
table.insert(cmd, v)
|
||||||
|
end
|
||||||
|
|
||||||
|
tags.modify(unpack(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
tags.rm = function(...)
|
||||||
|
local cmd = {"-remove-tags"}
|
||||||
|
local arg = {...}
|
||||||
|
for _, v in ipairs(arg) do
|
||||||
|
table.insert(cmd, v)
|
||||||
|
end
|
||||||
|
tags.modify(unpack(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
tags.clear = function()
|
||||||
|
local cmd = {"-clear-tags"}
|
||||||
|
tags.modify(unpack(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
return tags
|
@ -0,0 +1,158 @@
|
|||||||
|
M = {
|
||||||
|
-- query_struct = "(type_spec name:(type_identifier) @definition.struct type: (struct_type))",
|
||||||
|
query_package = "(package_clause (package_identifier)@package.name)@package.clause",
|
||||||
|
|
||||||
|
query_struct_id = "(type_spec name:(type_identifier) @definition.struct (struct_type))",
|
||||||
|
|
||||||
|
query_em_struct_id = "(field_declaration name:(field_identifier) @definition.struct (struct_type))",
|
||||||
|
|
||||||
|
query_struct_block = "(type_declaration (type_spec name:(type_identifier) @struct.name type: (struct_type)))@struct.declaration",
|
||||||
|
|
||||||
|
query_em_struct_block = "(field_declaration name:(field_identifier)@struct.name type: (struct_type)) @struct.declaration",
|
||||||
|
|
||||||
|
query_struct_block_from_id = "((type_spec name:(type_identifier) type: (struct_type)))@block.struct_from_id",
|
||||||
|
|
||||||
|
--query_em_struct = "(field_declaration name:(field_identifier) @definition.struct type: (struct_type))",
|
||||||
|
query_interface_id = [[(type_declaration (type_spec name:(type_identifier) @interface.name type:(interface_type)))@interface.declaration]],
|
||||||
|
|
||||||
|
query_interface_method = [[(method_spec name: (field_identifier)@method.name)@interface.method.declaration]],
|
||||||
|
|
||||||
|
query_func = "((function_declaration name: (identifier)@function.name) @function.declaration)",
|
||||||
|
-- query_method = "(method_declaration receiver: (parameter_list (parameter_declaration name:(identifier)@method.receiver.name type:(type_identifier)@method.receiver.type)) name:(field_identifier)@method.name)@method.declaration"
|
||||||
|
|
||||||
|
query_method_name = [[(method_declaration
|
||||||
|
receiver: (parameter_list)@method.receiver
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
body:(block))@method.declaration]],
|
||||||
|
|
||||||
|
query_method_void = [[(method_declaration
|
||||||
|
receiver: (parameter_list
|
||||||
|
(parameter_declaration
|
||||||
|
name: (identifier)@method.receiver.name
|
||||||
|
type: (pointer_type)@method.receiver.type)
|
||||||
|
)
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
parameters: (parameter_list)@method.parameter
|
||||||
|
body:(block)
|
||||||
|
)@method.declaration]],
|
||||||
|
|
||||||
|
query_method_multi_ret = [[(method_declaration
|
||||||
|
receiver: (parameter_list
|
||||||
|
(parameter_declaration
|
||||||
|
name: (identifier)@method.receiver.name
|
||||||
|
type: (pointer_type)@method.receiver.type)
|
||||||
|
)
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
parameters: (parameter_list)@method.parameter
|
||||||
|
result: (parameter_list)@method.result
|
||||||
|
body:(block)
|
||||||
|
)@method.declaration]],
|
||||||
|
|
||||||
|
query_method_single_ret = [[(method_declaration
|
||||||
|
receiver: (parameter_list
|
||||||
|
(parameter_declaration
|
||||||
|
name: (identifier)@method.receiver.name
|
||||||
|
type: (pointer_type)@method.receiver.type)
|
||||||
|
)
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
parameters: (parameter_list)@method.parameter
|
||||||
|
result: (type_identifier)@method.result
|
||||||
|
body:(block)
|
||||||
|
)@method.declaration]],
|
||||||
|
|
||||||
|
query_tr_method_void = [[(method_declaration
|
||||||
|
receiver: (parameter_list
|
||||||
|
(parameter_declaration
|
||||||
|
name: (identifier)@method.receiver.name
|
||||||
|
type: (type_identifier)@method.receiver.type)
|
||||||
|
)
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
parameters: (parameter_list)@method.parameter
|
||||||
|
body:(block)
|
||||||
|
)@method.declaration]],
|
||||||
|
|
||||||
|
query_tr_method_multi_ret = [[(method_declaration
|
||||||
|
receiver: (parameter_list
|
||||||
|
(parameter_declaration
|
||||||
|
name: (identifier)@method.receiver.name
|
||||||
|
type: (type_identifier)@method.receiver.type)
|
||||||
|
)
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
parameters: (parameter_list)@method.parameter
|
||||||
|
result: (parameter_list)@method.result
|
||||||
|
body:(block)
|
||||||
|
)@method.declaration]],
|
||||||
|
|
||||||
|
query_tr_method_single_ret = [[(method_declaration
|
||||||
|
receiver: (parameter_list
|
||||||
|
(parameter_declaration
|
||||||
|
name: (identifier)@method.receiver.name
|
||||||
|
type: (type_identifier)@method.receiver.type)
|
||||||
|
)
|
||||||
|
name: (field_identifier)@method.name
|
||||||
|
parameters: (parameter_list)@method.parameter
|
||||||
|
result: (type_identifier)@method.result
|
||||||
|
body:(block)
|
||||||
|
)@method.declaration]]
|
||||||
|
}
|
||||||
|
function get_name_defaults()
|
||||||
|
return {
|
||||||
|
["func"] = "function",
|
||||||
|
["if"] = "if",
|
||||||
|
["else"] = "else",
|
||||||
|
["for"] = "for",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
M.get_struct_node_at_pos = function(row, col)
|
||||||
|
local query = require("go.ts.go").query_struct_block .. " " .. require("go.ts.go").query_em_struct_block
|
||||||
|
|
||||||
|
local nodes = require("go.ts.nodes")
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
|
||||||
|
return ns[#ns]
|
||||||
|
end
|
||||||
|
|
||||||
|
M.get_interface_node_at_pos = function(row, col)
|
||||||
|
local query = require("go.ts.go").query_interface_id
|
||||||
|
local nodes = require("go.ts.nodes")
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
|
||||||
|
return ns[#ns]
|
||||||
|
end
|
||||||
|
|
||||||
|
M.get_interface_method_node_at_pos = function(row, col)
|
||||||
|
local query = require("go.ts.go").query_interface_method
|
||||||
|
local nodes = require("go.ts.nodes")
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
|
||||||
|
return ns[#ns]
|
||||||
|
end
|
||||||
|
|
||||||
|
M.get_func_method_node_at_pos = function(row, col)
|
||||||
|
local query = require("go.ts.go").query_func .. " " .. require("go.ts.go").query_method_name
|
||||||
|
-- local query = require("go.ts.go").query_method_name
|
||||||
|
local nodes = require("go.ts.nodes")
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
|
||||||
|
if ns == nil then return nil end
|
||||||
|
return ns[#ns]
|
||||||
|
end
|
||||||
|
|
||||||
|
M.get_package_node_at_pos = function(row, col)
|
||||||
|
if row > 10 then return end
|
||||||
|
local query = require("go.ts.go").query_package
|
||||||
|
-- local query = require("go.ts.go").query_method_name
|
||||||
|
local nodes = require("go.ts.nodes")
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
|
||||||
|
if ns == nil then return nil end
|
||||||
|
return ns[#ns]
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
@ -0,0 +1,240 @@
|
|||||||
|
-- part of the code from polarmutex/contextprint.nvim
|
||||||
|
|
||||||
|
local ts_utils = require("nvim-treesitter.ts_utils")
|
||||||
|
local ts_query = require("nvim-treesitter.query")
|
||||||
|
local parsers = require("nvim-treesitter.parsers")
|
||||||
|
local locals = require("nvim-treesitter.locals")
|
||||||
|
local utils = require("go.ts.utils")
|
||||||
|
local ulog = require("go.utils").log
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- Array<node_wrapper>
|
||||||
|
M.intersect_nodes = function(nodes, row, col)
|
||||||
|
local found = {}
|
||||||
|
for idx = 1, #nodes do
|
||||||
|
local node = nodes[idx]
|
||||||
|
local sRow = node.dim.s.r
|
||||||
|
local sCol = node.dim.s.c
|
||||||
|
local eRow = node.dim.e.r
|
||||||
|
local eCol = node.dim.e.c
|
||||||
|
|
||||||
|
if utils.intersects(row, col, sRow, sCol, eRow, eCol) then
|
||||||
|
table.insert(found, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return found
|
||||||
|
end
|
||||||
|
|
||||||
|
M.count_parents = function(node)
|
||||||
|
local count = 0
|
||||||
|
local n = node.declaring_node
|
||||||
|
while n ~= nil do
|
||||||
|
n = n:parent()
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
-- @param nodes Array<node_wrapper>
|
||||||
|
-- perf note. I could memoize some values here...
|
||||||
|
M.sort_nodes = function(nodes)
|
||||||
|
table.sort(
|
||||||
|
nodes,
|
||||||
|
function(a, b)
|
||||||
|
return M.count_parents(a) < M.count_parents(b)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return nodes
|
||||||
|
end
|
||||||
|
|
||||||
|
-- local lang = vim.api.nvim_buf_get_option(bufnr, 'ft')
|
||||||
|
-- node_wrapper
|
||||||
|
-- returns [{
|
||||||
|
-- declaring_node = tsnode
|
||||||
|
-- dim: {s: {r, c}, e: {r, c}},
|
||||||
|
-- name: string
|
||||||
|
-- type: string
|
||||||
|
-- }]
|
||||||
|
M.get_nodes = function(query, lang, defaults, bufnr)
|
||||||
|
bufnr = bufnr or 0
|
||||||
|
local success, parsed_query =
|
||||||
|
pcall(
|
||||||
|
function()
|
||||||
|
return vim.treesitter.parse_query(lang, query)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
if not success then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local parser = parsers.get_parser(bufnr, lang)
|
||||||
|
local root = parser:parse()[1]:root()
|
||||||
|
local start_row, _, end_row, _ = root:range()
|
||||||
|
-- local n = ts_utils.get_node_at_cursor()
|
||||||
|
-- local a, b, c, d = ts_utils.get_node_range(n)
|
||||||
|
local results = {}
|
||||||
|
for match in ts_query.iter_prepared_matches(parsed_query, root, bufnr, start_row, end_row) do
|
||||||
|
local sRow, sCol, eRow, eCol
|
||||||
|
local declaration_node
|
||||||
|
local type = "nil"
|
||||||
|
local name = "nil"
|
||||||
|
locals.recurse_local_nodes(
|
||||||
|
match,
|
||||||
|
function(_, node, path)
|
||||||
|
local idx = string.find(path, ".", 1, true)
|
||||||
|
local op = string.sub(path, idx + 1, #path)
|
||||||
|
|
||||||
|
local a1, b1, c1, d1 = ts_utils.get_node_range(node)
|
||||||
|
|
||||||
|
type = string.sub(path, 1, idx - 1)
|
||||||
|
if name == nil then
|
||||||
|
name = defaults[type] or "empty"
|
||||||
|
end
|
||||||
|
|
||||||
|
if op == "name" then
|
||||||
|
name = ts_utils.get_node_text(node)[1]
|
||||||
|
elseif op == "declaration" then
|
||||||
|
declaration_node = node
|
||||||
|
sRow, sCol, eRow, eCol = node:range()
|
||||||
|
sRow = sRow + 1
|
||||||
|
eRow = eRow + 1
|
||||||
|
sCol = sCol + 1
|
||||||
|
eCol = eCol + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
if declaration_node ~= nil then
|
||||||
|
table.insert(
|
||||||
|
results,
|
||||||
|
{
|
||||||
|
declaring_node = declaration_node,
|
||||||
|
dim = {
|
||||||
|
s = {r = sRow, c = sCol},
|
||||||
|
e = {r = eRow, c = eCol}
|
||||||
|
},
|
||||||
|
name = name,
|
||||||
|
type = type
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
-- local lang = vim.api.nvim_buf_get_option(bufnr, 'ft')
|
||||||
|
-- node_wrapper
|
||||||
|
-- returns {
|
||||||
|
-- declaring_node = tsnode
|
||||||
|
-- dim: {s: {r, c}, e: {r, c}},
|
||||||
|
-- name: string
|
||||||
|
-- type: string
|
||||||
|
-- }
|
||||||
|
M.get_all_nodes = function(query, lang, defaults, bufnr, pos_row, pos_col)
|
||||||
|
bufnr = bufnr or 0
|
||||||
|
-- todo a huge number
|
||||||
|
pos_row = pos_row or 30000
|
||||||
|
local success, parsed_query =
|
||||||
|
pcall(
|
||||||
|
function()
|
||||||
|
return vim.treesitter.parse_query(lang, query)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
if not success then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local parser = parsers.get_parser(bufnr, lang)
|
||||||
|
local root = parser:parse()[1]:root()
|
||||||
|
local start_row, _, end_row, _ = root:range()
|
||||||
|
-- local n = ts_utils.get_node_at_cursor()
|
||||||
|
-- local a, b, c, d = ts_utils.get_node_range(n)
|
||||||
|
-- ulog("node range " .. tostring(a) .. tostring(b) .. tostring(c).. tostring(d))
|
||||||
|
-- ulog("cru node:" .. vim.inspect(n) .. "text: " .. vim.inspect(ts_utils.get_node_text(n)))
|
||||||
|
local results = {}
|
||||||
|
for match in ts_query.iter_prepared_matches(parsed_query, root, bufnr, start_row, end_row) do
|
||||||
|
local sRow, sCol, eRow, eCol
|
||||||
|
local declaration_node
|
||||||
|
local type = ""
|
||||||
|
local name = ""
|
||||||
|
local op = ""
|
||||||
|
local method_receiver = ""
|
||||||
|
|
||||||
|
locals.recurse_local_nodes(
|
||||||
|
match,
|
||||||
|
function(_, node, path)
|
||||||
|
--local idx = string.find(path, ".", 1, true)
|
||||||
|
local idx = string.find(path, ".[^.]*$") -- find last .
|
||||||
|
op = string.sub(path, idx + 1, #path)
|
||||||
|
local a1, b1, c1, d1 = ts_utils.get_node_range(node)
|
||||||
|
local dbg_txt = ts_utils.get_node_text(node, bufnr)[1]
|
||||||
|
type = string.sub(path, 1, idx - 1)
|
||||||
|
|
||||||
|
ulog( "node" .. vim.inspect(node) .. "\n path: " .. path .. " op: " .. op .. " type: " .. type .. "\n txt: " .. dbg_txt .. "\n range: " .. tostring(a1) .. ":" .. tostring(b1) .. " TO " .. tostring(c1) .. ":" .. tostring(d1))
|
||||||
|
--
|
||||||
|
-- may not handle complex node
|
||||||
|
if op == "name" then
|
||||||
|
-- ulog("node name " .. name)
|
||||||
|
name = ts_utils.get_node_text(node, bufnr)[1]
|
||||||
|
elseif op == "declaration" or op == "clause" then
|
||||||
|
declaration_node = node
|
||||||
|
sRow, sCol, eRow, eCol = node:range()
|
||||||
|
sRow = sRow + 1
|
||||||
|
eRow = eRow + 1
|
||||||
|
sCol = sCol + 1
|
||||||
|
eCol = eCol + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
if declaration_node ~= nil then
|
||||||
|
-- ulog(name .. " " .. op)
|
||||||
|
-- ulog(sRow, pos_row)
|
||||||
|
if sRow > pos_row then
|
||||||
|
ulog("beyond " .. tostring(pos_row))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
table.insert(
|
||||||
|
results,
|
||||||
|
{
|
||||||
|
declaring_node = declaration_node,
|
||||||
|
dim = {
|
||||||
|
s = {r = sRow, c = sCol},
|
||||||
|
e = {r = eRow, c = eCol}
|
||||||
|
},
|
||||||
|
name = name,
|
||||||
|
operator = op,
|
||||||
|
type = type
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- ulog("total nodes got: " .. tostring(#results))
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
M.nodes_at_cursor = function(query, default, bufnr, row, col)
|
||||||
|
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||||
|
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
|
||||||
|
if row == nil or col == nil then
|
||||||
|
row, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||||
|
row, col = row + 1, col + 1
|
||||||
|
end
|
||||||
|
local nodes = M.get_all_nodes(query, ft, default, bufnr, row, col)
|
||||||
|
if nodes == nil then
|
||||||
|
print("Unable to find any nodes. Is your query correct?")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
nodes = M.sort_nodes(M.intersect_nodes(nodes, row, col))
|
||||||
|
if nodes == nil or #nodes == 0 then
|
||||||
|
print("Unable to find any nodes at pos. " .. tostring(row) .. ":" .. tostring(col))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return nodes
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
@ -0,0 +1,19 @@
|
|||||||
|
local M = {}
|
||||||
|
M.intersects = function(row, col, sRow, sCol, eRow, eCol)
|
||||||
|
-- print(row, col, sRow, sCol, eRow, eCol)
|
||||||
|
if sRow > row or eRow < row then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if sRow == row and sCol > col then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if eRow == row and eCol < col then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
@ -0,0 +1,41 @@
|
|||||||
|
local util = {}
|
||||||
|
util.check_same = function(tbl1, tbl2)
|
||||||
|
if #tbl1 ~= #tbl2 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for k, v in ipairs(tbl1) do
|
||||||
|
if v ~= tbl2[k] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
util.copy_array = function(from, to)
|
||||||
|
for i = 1, #from do
|
||||||
|
to[i] = from[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
util.deepcopy = function (orig)
|
||||||
|
local orig_type = type(orig)
|
||||||
|
local copy
|
||||||
|
if orig_type == 'table' then
|
||||||
|
copy = {}
|
||||||
|
for orig_key, orig_value in next, orig, nil do
|
||||||
|
copy[util.deepcopy(orig_key)] = util.deepcopy(orig_value)
|
||||||
|
end
|
||||||
|
setmetatable(copy, util.deepcopy(getmetatable(orig)))
|
||||||
|
else -- number, string, boolean, etc
|
||||||
|
copy = orig
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
util.log = function(...)
|
||||||
|
if vim.g.go_nvim_verbose then
|
||||||
|
print(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return util
|
@ -0,0 +1,5 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
MyHomeAddress string `json:"my_home_address"`
|
||||||
|
SubDomains []string `json:"sub_domains"`
|
||||||
|
Empty string `json:"empty"`
|
||||||
|
Example int64 `json:"example"`
|
||||||
|
Example2 string `json:"example_2"`
|
||||||
|
Bar struct {
|
||||||
|
Four string `json:"four"`
|
||||||
|
Five string `json:"five"`
|
||||||
|
} `json:"bar"`
|
||||||
|
Lala interface{} `json:"lala"`
|
||||||
|
} //eos
|
||||||
|
//eof
|
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
ID int `json:"id,omitempty"`
|
||||||
|
MyHomeAddress string `json:"my_home_address,omitempty"`
|
||||||
|
SubDomains []string `json:"sub_domains,omitempty"`
|
||||||
|
Empty string `json:"empty,omitempty"`
|
||||||
|
Example int64 `json:"example,omitempty"`
|
||||||
|
Example2 string `json:"example_2,omitempty"`
|
||||||
|
Bar struct {
|
||||||
|
Four string `json:"four,omitempty"`
|
||||||
|
Five string `json:"five,omitempty"`
|
||||||
|
} `json:"bar,omitempty"`
|
||||||
|
Lala interface{} `json:"lala,omitempty"`
|
||||||
|
} //eos
|
||||||
|
//eof
|
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string
|
||||||
|
ID int
|
||||||
|
MyHomeAddress string
|
||||||
|
SubDomains []string
|
||||||
|
Empty string
|
||||||
|
Example int64
|
||||||
|
Example2 string
|
||||||
|
Bar struct {
|
||||||
|
Four string
|
||||||
|
Five string
|
||||||
|
}
|
||||||
|
Lala interface{}
|
||||||
|
} //eos
|
||||||
|
//eof
|
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string
|
||||||
|
ID int
|
||||||
|
MyHomeAddress string
|
||||||
|
SubDomains []string
|
||||||
|
Empty string
|
||||||
|
Example int64
|
||||||
|
Example2 string
|
||||||
|
Bar struct {
|
||||||
|
Four string
|
||||||
|
Five string
|
||||||
|
}
|
||||||
|
Lala interface{}
|
||||||
|
} //eos
|
||||||
|
//eof
|
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
MyHomeAddress string `json:"my_home_address"`
|
||||||
|
SubDomains []string `json:"sub_domains"`
|
||||||
|
Empty string `json:"empty"`
|
||||||
|
Example int64 `json:"example"`
|
||||||
|
Example2 string `json:"example_2"`
|
||||||
|
Bar struct {
|
||||||
|
Four string `json:"four"`
|
||||||
|
Five string `json:"five"`
|
||||||
|
} `json:"bar"`
|
||||||
|
Lala interface{} `json:"lala"`
|
||||||
|
} //eos
|
||||||
|
//eof
|
@ -0,0 +1,48 @@
|
|||||||
|
// https://gobyexample.com/interfaces
|
||||||
|
//
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Geometry interface {
|
||||||
|
Area() float64
|
||||||
|
perim() float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type rect struct {
|
||||||
|
width, height float64
|
||||||
|
}
|
||||||
|
type circle struct {
|
||||||
|
radius float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r rect) Area() float64 {
|
||||||
|
return r.width * r.height
|
||||||
|
}
|
||||||
|
func (r rect) perim() float64 {
|
||||||
|
return 2*r.width + 2*r.height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c circle) Area() float64 {
|
||||||
|
return math.Pi * c.radius * c.radius
|
||||||
|
}
|
||||||
|
func (c circle) perim() float64 {
|
||||||
|
return 2 * math.Pi * c.radius
|
||||||
|
}
|
||||||
|
|
||||||
|
func measure(g Geometry) {
|
||||||
|
fmt.Println(g)
|
||||||
|
fmt.Println(g.Area())
|
||||||
|
fmt.Println(g.perim())
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := rect{width: 3, height: 4}
|
||||||
|
c := circle{radius: 5}
|
||||||
|
|
||||||
|
measure(r)
|
||||||
|
measure(c)
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
// code form https://medium.com/backendarmy/linked-lists-in-go-f7a7b27a03b9
|
||||||
|
// this code is use to test treesiter parser
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type song struct {
|
||||||
|
name string
|
||||||
|
artist string
|
||||||
|
next *song
|
||||||
|
}
|
||||||
|
|
||||||
|
type playlist struct {
|
||||||
|
name string
|
||||||
|
head *song
|
||||||
|
nowPlaying *song
|
||||||
|
}
|
||||||
|
|
||||||
|
func createPlaylist(name string) *playlist {
|
||||||
|
return &playlist{
|
||||||
|
name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playlist) addSong(name, artist string) error {
|
||||||
|
s := &song{
|
||||||
|
name: name,
|
||||||
|
artist: artist,
|
||||||
|
}
|
||||||
|
if p.head == nil {
|
||||||
|
p.head = s
|
||||||
|
} else {
|
||||||
|
currentNode := p.head
|
||||||
|
for currentNode.next != nil {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
currentNode.next = s
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playlist) showAllSongs() error {
|
||||||
|
currentNode := p.head
|
||||||
|
if currentNode == nil {
|
||||||
|
fmt.Println("Playlist is empty.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("%+v\n", *currentNode)
|
||||||
|
for currentNode.next != nil {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
fmt.Printf("%+v\n", *currentNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playlist) startPlaying() *song {
|
||||||
|
p.nowPlaying = p.head
|
||||||
|
return p.nowPlaying
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playlist) nextSong() *song {
|
||||||
|
p.nowPlaying = p.nowPlaying.next
|
||||||
|
return p.nowPlaying
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playlist) NextSong() *song { // exported
|
||||||
|
p.nowPlaying = p.nowPlaying.next
|
||||||
|
return p.nowPlaying
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
playlistName := "myplaylist"
|
||||||
|
myPlaylist := createPlaylist(playlistName)
|
||||||
|
fmt.Println("Created playlist")
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Print("Adding songs to the playlist...\n\n")
|
||||||
|
myPlaylist.addSong("Ophelia", "The Lumineers")
|
||||||
|
myPlaylist.addSong("Shape of you", "Ed Sheeran")
|
||||||
|
myPlaylist.addSong("Stubborn Love", "The Lumineers")
|
||||||
|
myPlaylist.addSong("Feels", "Calvin Harris")
|
||||||
|
fmt.Println("Showing all songs in playlist...")
|
||||||
|
myPlaylist.showAllSongs()
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
myPlaylist.startPlaying()
|
||||||
|
fmt.Printf("Now playing: %s by %s\n", myPlaylist.nowPlaying.name, myPlaylist.nowPlaying.artist)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
myPlaylist.nextSong()
|
||||||
|
fmt.Println("Changing next song...")
|
||||||
|
fmt.Printf("Now playing: %s by %s\n", myPlaylist.nowPlaying.name, myPlaylist.nowPlaying.artist)
|
||||||
|
fmt.Println()
|
||||||
|
myPlaylist.nextSong()
|
||||||
|
fmt.Println("Changing next song...")
|
||||||
|
fmt.Printf("Now playing: %s by %s\n", myPlaylist.nowPlaying.name, myPlaylist.nowPlaying.artist)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
local eq = assert.are.same
|
||||||
|
|
||||||
|
local busted = require("plenary/busted")
|
||||||
|
local cur_dir = vim.fn.expand("%:p:h")
|
||||||
|
describe(
|
||||||
|
"should get nodes ",
|
||||||
|
function()
|
||||||
|
vim.g.go_nvim_verbose = true
|
||||||
|
vim.g.go_nvim_comment_placeholder = "go.nvim"
|
||||||
|
|
||||||
|
local status = require("plenary.reload").reload_module("go.nvim")
|
||||||
|
status = require("plenary.reload").reload_module("nvim-treesitter/nvim-treesitter")
|
||||||
|
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/playlist.go" -- %:p:h ? %:p
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = "silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
it(
|
||||||
|
"should get struct playlist and generate comments",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 20, 14, 0})
|
||||||
|
local query = require("go.comment").gen(20, 14)
|
||||||
|
eq("// createPlaylist function go.nvim", query)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should get struct playlist and generate comments",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 14, 4, 0})
|
||||||
|
local query = require("go.comment").gen(14, 4)
|
||||||
|
eq("// playlist struct go.nvim", query)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
@ -0,0 +1,129 @@
|
|||||||
|
|
||||||
|
local eq = assert.are.same
|
||||||
|
local cur_dir = vim.fn.expand("%:p:h")
|
||||||
|
|
||||||
|
describe(
|
||||||
|
"should run gofmt",
|
||||||
|
function()
|
||||||
|
--vim.fn.readfile('minimal.vim')
|
||||||
|
-- vim.fn.writefile(vim.fn.readfile('fixtures/fmt/hello.go'), name)
|
||||||
|
status = require("plenary.reload").reload_module("go.nvim")
|
||||||
|
it(
|
||||||
|
"should run fmt",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/fmt/hello.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local expected =
|
||||||
|
vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/fmt/hello_golden.go"), "\n")
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
print("buf read: " .. vim.inspect(l))
|
||||||
|
|
||||||
|
vim.bo.filetype = "go"
|
||||||
|
|
||||||
|
print("exp:" .. vim.inspect(expected))
|
||||||
|
print("tmp" .. name)
|
||||||
|
|
||||||
|
local gofmt = require("go.format")
|
||||||
|
gofmt.gofmt()
|
||||||
|
-- enable the channel response
|
||||||
|
vim.wait(100, function () end)
|
||||||
|
local fmt =
|
||||||
|
vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
print("fmt" .. fmt)
|
||||||
|
vim.fn.assert_equal(fmt, expected)
|
||||||
|
eq(expected, fmt)
|
||||||
|
local cmd = "bd! ".. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should run fmt sending from buffer",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/fmt/hello.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local expected =
|
||||||
|
vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/fmt/hello_golden.go"), "\n")
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
print("buf read: " .. vim.inspect(l))
|
||||||
|
|
||||||
|
vim.bo.filetype = "go"
|
||||||
|
|
||||||
|
print("exp:" .. vim.inspect(expected))
|
||||||
|
print("tmp" .. name)
|
||||||
|
|
||||||
|
local gofmt = require("go.format")
|
||||||
|
gofmt.gofmt(true)
|
||||||
|
-- enable the channel response
|
||||||
|
vim.wait(100, function () end)
|
||||||
|
local fmt =
|
||||||
|
vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
print("fmt" .. fmt)
|
||||||
|
vim.fn.assert_equal(fmt, expected)
|
||||||
|
eq(expected, fmt)
|
||||||
|
local cmd = "bd! ".. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should run import from file",
|
||||||
|
function()
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/fmt/goimports.go" -- %:p:h ? %:p
|
||||||
|
local expected = vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/fmt/goimports_golden.go"), "\n")
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print(name)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local gofmt = require("go.format")
|
||||||
|
gofmt.goimport()
|
||||||
|
vim.wait( 100, function() end)
|
||||||
|
local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
eq(expected, fmt)
|
||||||
|
cmd = "bd! " .. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should run import from file buffer",
|
||||||
|
function()
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/fmt/goimports.go" -- %:p:h ? %:p
|
||||||
|
local expected = vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/fmt/goimports_golden.go"), "\n")
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print(name)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
vim.cmd(cmd)
|
||||||
|
|
||||||
|
print("code write to " .. name)
|
||||||
|
local gofmt = require("go.format")
|
||||||
|
gofmt.goimport(true)
|
||||||
|
|
||||||
|
vim.wait(
|
||||||
|
100,
|
||||||
|
function()
|
||||||
|
end
|
||||||
|
)
|
||||||
|
local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
|
||||||
|
print(fmt)
|
||||||
|
eq(expected, fmt)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
@ -0,0 +1,162 @@
|
|||||||
|
local helpers = {}
|
||||||
|
local busted = require("plenary/busted")
|
||||||
|
|
||||||
|
local eq = assert.are.same
|
||||||
|
local cur_dir = vim.fn.expand("%:p:h")
|
||||||
|
local ulog = require('go.utils').log
|
||||||
|
describe(
|
||||||
|
"should run gotags",
|
||||||
|
function()
|
||||||
|
--vim.fn.readfile('minimal.vim')
|
||||||
|
-- vim.fn.writefile(vim.fn.readfile('fixtures/fmt/hello.go'), name)
|
||||||
|
status = require("plenary.reload").reload_module("go.nvim")
|
||||||
|
it(
|
||||||
|
"should run add json tags",
|
||||||
|
function()
|
||||||
|
--
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/tags/add_all_input.go" -- %:p:h ? %:p
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local expected =
|
||||||
|
vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/tags/add_all_golden.go"), "\n")
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 4, 0})
|
||||||
|
|
||||||
|
|
||||||
|
local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
-- ulog("buf read: " .. vim.inspect(l))
|
||||||
|
|
||||||
|
vim.bo.filetype = "go"
|
||||||
|
|
||||||
|
-- ulog("exp:" .. vim.inspect(expected))
|
||||||
|
|
||||||
|
local gotags = require("go.tags")
|
||||||
|
gotags.add()
|
||||||
|
-- enable the channel response
|
||||||
|
vim.wait(100, function () end)
|
||||||
|
local fmt =
|
||||||
|
vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
-- ulog("tagged file: " .. fmt)
|
||||||
|
vim.fn.assert_equal(fmt, expected)
|
||||||
|
eq(expected, fmt)
|
||||||
|
local cmd = "bd! ".. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should rm json tags",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/tags/add_all_golden.go" -- %:p:h ? %:p
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local expected =
|
||||||
|
vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/tags/add_all_input.go"), "\n")
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 4, 0})
|
||||||
|
|
||||||
|
|
||||||
|
local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
-- ulog("buf read: " .. vim.inspect(l))
|
||||||
|
|
||||||
|
vim.bo.filetype = "go"
|
||||||
|
|
||||||
|
-- ulog("exp:" .. vim.inspect(expected))
|
||||||
|
|
||||||
|
local gotags = require("go.tags")
|
||||||
|
gotags.rm('json')
|
||||||
|
-- enable the channel response
|
||||||
|
vim.wait(100, function () end)
|
||||||
|
local fmt =
|
||||||
|
vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
-- ulog("tagged file: " .. fmt)
|
||||||
|
vim.fn.assert_equal(fmt, expected)
|
||||||
|
eq(expected, fmt)
|
||||||
|
local cmd = "bd! ".. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should run clear json tags by default",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/tags/add_all_golden.go" -- %:p:h ? %:p
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local expected =
|
||||||
|
vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/tags/add_all_input.go"), "\n")
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 4, 0})
|
||||||
|
|
||||||
|
|
||||||
|
local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
-- ulog("buf read: " .. vim.inspect(l))
|
||||||
|
|
||||||
|
vim.bo.filetype = "go"
|
||||||
|
|
||||||
|
-- ulog("exp:" .. vim.inspect(expected))
|
||||||
|
|
||||||
|
local gotags = require("go.tags")
|
||||||
|
gotags.rm()
|
||||||
|
-- enable the channel response
|
||||||
|
vim.wait(100, function () end)
|
||||||
|
local fmt =
|
||||||
|
vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
-- ulog("tagged file: " .. fmt)
|
||||||
|
vim.fn.assert_equal(fmt, expected)
|
||||||
|
eq(expected, fmt)
|
||||||
|
local cmd = "bd! ".. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should clear all tags",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/tags/add_all_golden.go" -- %:p:h ? %:p
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local expected =
|
||||||
|
vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/tags/add_all_input.go"), "\n")
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 4, 0})
|
||||||
|
|
||||||
|
|
||||||
|
local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||||
|
-- ulog("buf read: " .. vim.inspect(l))
|
||||||
|
|
||||||
|
vim.bo.filetype = "go"
|
||||||
|
|
||||||
|
-- ulog("exp:" .. vim.inspect(expected))
|
||||||
|
|
||||||
|
local gotags = require("go.tags")
|
||||||
|
gotags.rm()
|
||||||
|
-- enable the channel response
|
||||||
|
vim.wait(100, function () end)
|
||||||
|
local fmt =
|
||||||
|
vim.fn.join(vim.fn.readfile(name), "\n")
|
||||||
|
-- ulog("tagged file: " .. fmt)
|
||||||
|
vim.fn.assert_equal(fmt, expected)
|
||||||
|
eq(expected, fmt)
|
||||||
|
local cmd = "bd! ".. name
|
||||||
|
vim.cmd(cmd)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
@ -0,0 +1,211 @@
|
|||||||
|
local eq = assert.are.same
|
||||||
|
local input = {
|
||||||
|
"package a",
|
||||||
|
"",
|
||||||
|
"type x struct {",
|
||||||
|
"\tFoo int",
|
||||||
|
"\tbar int",
|
||||||
|
"\ty struct {",
|
||||||
|
"\t\tFoo int",
|
||||||
|
"\t\tbar int",
|
||||||
|
"\t}",
|
||||||
|
"}",
|
||||||
|
"type z struct{}"
|
||||||
|
}
|
||||||
|
|
||||||
|
local default = {
|
||||||
|
["function"] = "func",
|
||||||
|
["method"] = "func",
|
||||||
|
["struct"] = "struct",
|
||||||
|
["interface"] = "interface"
|
||||||
|
}
|
||||||
|
|
||||||
|
local output_inner = {
|
||||||
|
"package a",
|
||||||
|
"",
|
||||||
|
"type x struct {",
|
||||||
|
'\tFoo int `xx:"foo"`',
|
||||||
|
'\tbar int `xx:"bar"`',
|
||||||
|
"y struct {",
|
||||||
|
'\t\tFoo int `xx:"foo"`',
|
||||||
|
'\t\tbar int `xx:"bar"`',
|
||||||
|
"}",
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
describe(
|
||||||
|
"should get nodes ",
|
||||||
|
function()
|
||||||
|
vim.cmd([[silent exe 'e tags.go']])
|
||||||
|
vim.fn.append(0, input)
|
||||||
|
local bufn = vim.fn.bufnr("")
|
||||||
|
status = require("plenary.reload").reload_module("go.nvim")
|
||||||
|
status = require("plenary.reload").reload_module("nvim-treesitter/nvim-treesitter")
|
||||||
|
vim.g.go_nvim_verbose = true
|
||||||
|
local cur_dir = vim.fn.expand("%:p:h")
|
||||||
|
local nodes = require("go.ts.nodes")
|
||||||
|
it(
|
||||||
|
"get all nodes should get struct x",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 4, 1, 0})
|
||||||
|
local query = require("go.ts.go").query_struct_block
|
||||||
|
local ns = nodes.get_all_nodes(query, "go", default, bufn)
|
||||||
|
eq("x", ns[1].name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"it should get struct y",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 1, 0})
|
||||||
|
local query = require("go.ts.go").query_struct_block .. require("go.ts.go").query_em_struct_block
|
||||||
|
-- local query = require('go.ts.go').query_em_struct
|
||||||
|
local ns = nodes.get_all_nodes(query, "go", default, bufn)
|
||||||
|
eq("y", ns[2].name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"node at cursor should get struct x",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 4, 1, 0})
|
||||||
|
local query = require("go.ts.go").query_struct_block
|
||||||
|
local ns = nodes.nodes_at_cursor(query, default, bufn)
|
||||||
|
eq("x", ns[1].name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"it should get struct y",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 1, 0})
|
||||||
|
local query = require("go.ts.go").query_struct_block .. require("go.ts.go").query_em_struct_block
|
||||||
|
-- local query = require('go.ts.go').query_em_struct
|
||||||
|
local ns = nodes.nodes_at_cursor(query, default, bufn)
|
||||||
|
eq("y", ns[#ns].name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"struct at pos should get struct y",
|
||||||
|
function()
|
||||||
|
vim.fn.setpos(".", {bufn, 8, 4, 0})
|
||||||
|
local ns = require("go.ts.go").get_struct_node_at_pos(8, 1)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("y", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get function name",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/playlist.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 21, 5, 0})
|
||||||
|
local ns = require("go.ts.go").get_func_method_node_at_pos(21, 5)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("createPlaylist", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get method (with par list) name",
|
||||||
|
function()
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/playlist.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local cmd = " silent exe 'e " .. path .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 33, 21, 0})
|
||||||
|
local ns = require("go.ts.go").get_func_method_node_at_pos(33, 21)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("addSong", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get method (no par) name",
|
||||||
|
function()
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/playlist.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local cmd = " silent exe 'e " .. path .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 48, 3, 0})
|
||||||
|
local ns = require("go.ts.go").get_func_method_node_at_pos(48, 3)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("showAllSongs", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get interface name",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/interfaces.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 11, 6, 0})
|
||||||
|
local ns = require("go.ts.go").get_interface_node_at_pos(11, 6)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("Geometry", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get interface method name",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/interfaces.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 11, 5, 0})
|
||||||
|
local ns = require("go.ts.go").get_interface_method_node_at_pos(11, 5)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("Area", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get package name",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/interfaces.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 3, 5, 0})
|
||||||
|
local ns = require("go.ts.go").get_package_node_at_pos(3, 5)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("main", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
it(
|
||||||
|
"should get package name",
|
||||||
|
function()
|
||||||
|
local name = vim.fn.tempname() .. ".go"
|
||||||
|
print("tmp:" .. name)
|
||||||
|
--
|
||||||
|
local path = cur_dir .. "/lua/tests/fixtures/ts/interfaces.go" -- %:p:h ? %:p
|
||||||
|
print("test:" .. path)
|
||||||
|
local lines = vim.fn.readfile(path)
|
||||||
|
vim.fn.writefile(lines, name)
|
||||||
|
local cmd = " silent exe 'e " .. name .. "'"
|
||||||
|
vim.cmd(cmd)
|
||||||
|
vim.fn.setpos(".", {bufn, 3, 1, 0})
|
||||||
|
local ns = require("go.ts.go").get_package_node_at_pos(3, 1)
|
||||||
|
print(vim.inspect(ns))
|
||||||
|
eq("main", ns.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
@ -0,0 +1,6 @@
|
|||||||
|
set rtp +=.
|
||||||
|
set rtp +=~/.vim/autoload/plenary.nvim/
|
||||||
|
runtime! plugin/plenary.vim
|
||||||
|
|
||||||
|
lua require("plenary/busted")
|
||||||
|
lua require("go.nvim")
|
Loading…
Reference in New Issue