allow format all buffers with goimports

pull/130/head
ray-x 2 years ago
parent 58dd76bf90
commit eb4d380807

@ -306,10 +306,12 @@ gofmt)
| command | Description | | command | Description |
| --------------------- | --------------------------- | | --------------------- | --------------------------- |
| GoFmt | goline + gofumpt | | GoFmt {opts} | goline + gofumpt |
| GoImport | goline + goimport + gofumpt | | GoImport | goline + goimport + gofumpt |
| GoImport package_path | gopls add_import package | | GoImport package_path | gopls add_import package |
{opts} : ``-a`` format all buffers
## GoImpl ## GoImpl
generate method stubs for implementing an interface generate method stubs for implementing an interface

@ -164,7 +164,7 @@ COMMANDS *go-nvim-commands*
au Syntax go hi goCoverageCovered guibg=green au Syntax go hi goCoverageCovered guibg=green
au Syntax go hi goCoverageUncover guibg=brown au Syntax go hi goCoverageUncover guibg=brown
augroup end augroup end
:GoImport *:GoImport* :GoImport {package_name} *:GoImport*
Add, modify imports. Add, modify imports.
:GoBuild {-tags=tagname}{pakcage_name} *:GoBuild* :GoBuild {-tags=tagname}{pakcage_name} *:GoBuild*
@ -191,8 +191,8 @@ COMMANDS *go-nvim-commands*
:GoAddTest *:GoAddTest* :GoAddTest *:GoAddTest*
Add unit test for current function Add unit test for current function
:GoFmt {-tags=tagname}{pakcage_name} *:GoFmt* :GoFmt {-a} *:GoFmt*
Format code with golines+gofumpt package Format code with golines+gofumpt. -a: apply to all files
:GoVet *:GoVet* :GoVet *:GoVet*
Run go vet Run go vet
:GoCheat query *:GoCheat* :GoCheat query *:GoCheat*

@ -91,7 +91,7 @@ function go.setup(cfg)
vim.cmd([[command! GoMake silent lua require'go.asyncmake'.make()]]) vim.cmd([[command! GoMake silent lua require'go.asyncmake'.make()]])
vim.cmd([[command! GoFmt lua require("go.format").gofmt()]]) vim.cmd([[command! -nargs=* GoFmt lua require("go.format").gofmt({<f-args>})]])
vim.cmd( vim.cmd(
[[command! -nargs=* -complete=custom,v:lua.package.loaded.go.doc_complete GoImport lua require("go.format").goimport(<f-args>)]] [[command! -nargs=* -complete=custom,v:lua.package.loaded.go.doc_complete GoImport lua require("go.format").goimport(<f-args>)]]

@ -14,20 +14,28 @@ local gofmt_args = _GO_NVIM_CFG.gofmt_args or {
local goimport_args = _GO_NVIM_CFG.goimport_args local goimport_args = _GO_NVIM_CFG.goimport_args
or { or {
"--max-len=" .. tostring(max_len), "--max-len=" .. tostring(max_len),
"--base-formatter=" .. goimport, "--base-formatter=goimports",
} }
local run = function(fmtargs, from_buffer, cmd) local run = function(fmtargs, bufnr, cmd)
local args = vim.deepcopy(fmtargs) log(fmtargs, bufnr, cmd)
if not from_buffer then bufnr = bufnr or 0
table.insert(args, api.nvim_buf_get_name(0)) if _GO_NVIM_CFG.gofmt == "gopls" then
log("formatting buffer... " .. api.nvim_buf_get_name(0) .. vim.inspect(args), vim.lsp.log_levels.DEBUG) if not vim.api.nvim_buf_is_loaded(bufnr) then
else vim.fn.bufload(bufnr)
log("formatting... " .. vim.inspect(args), vim.lsp.log_levels.DEBUG) end
vim.lsp.buf.format({ async = true, bufnr = bufnr })
return
end end
if vim.fn.getbufinfo('%')[1].changed == 1 then local args = vim.deepcopy(fmtargs)
api.nvim_command("w") table.insert(args, api.nvim_buf_get_name(bufnr))
log("formatting buffer... " .. vim.inspect(args), vim.lsp.log_levels.DEBUG)
if bufnr == 0 then
if vim.fn.getbufinfo("%")[1].changed == 1 then
api.cmd("write")
end
end end
local old_lines = api.nvim_buf_get_lines(0, 0, -1, true) local old_lines = api.nvim_buf_get_lines(0, 0, -1, true)
@ -47,7 +55,7 @@ local run = function(fmtargs, from_buffer, cmd)
if not utils.check_same(old_lines, data) then if not utils.check_same(old_lines, data) then
vim.notify("updating codes", vim.lsp.log_levels.DEBUG) vim.notify("updating codes", vim.lsp.log_levels.DEBUG)
api.nvim_buf_set_lines(0, 0, -1, false, data) api.nvim_buf_set_lines(0, 0, -1, false, data)
api.nvim_command("write") vim.cmd("write")
else else
vim.notify("already formatted", vim.lsp.log_levels.DEBUG) vim.notify("already formatted", vim.lsp.log_levels.DEBUG)
end end
@ -62,7 +70,7 @@ local run = function(fmtargs, from_buffer, cmd)
-- log(vim.inspect(data) .. "exit") -- log(vim.inspect(data) .. "exit")
-- log("current data " .. vim.inspect(new_lines)) -- log("current data " .. vim.inspect(new_lines))
old_lines = nil old_lines = nil
vim.cmd('write') vim.cmd("write")
end, end,
stdout_buffered = true, stdout_buffered = true,
stderr_buffered = true, stderr_buffered = true,
@ -72,19 +80,41 @@ local run = function(fmtargs, from_buffer, cmd)
end end
local M = {} local M = {}
M.gofmt = function(buf) M.gofmt = function(...)
if _GO_NVIM_CFG.gofmt == "gopls" then local long_opts = {
-- log("gopls format") all = "a",
vim.lsp.buf.format({ async = true }) }
return
end local short_opts = "a"
local args = ... or {}
local getopt = require("go.alt_getopt")
local optarg, optind, reminder = getopt.get_opts(args, short_opts, long_opts)
log(optarg)
vim.env.GO_FMT = "gofumpt" vim.env.GO_FMT = "gofumpt"
buf = buf or false local all_buf = false
if optarg["a"] then
all_buf = true
end
require("go.install").install(gofmt) require("go.install").install(gofmt)
require("go.install").install("golines") require("go.install").install("golines")
local a = {} local a = {}
utils.copy_array(gofmt_args, a) utils.copy_array(gofmt_args, a)
run(a, buf) if all_buf then
log("fmt all buffers")
vim.cmd("wall")
local bufs = utils.get_active_buf()
log(bufs)
for _, b in ipairs(bufs) do
log(a, b)
run(a, b.bufnr)
end
else
vim.cmd("write")
run(a, 0)
end
end end
M.org_imports = function(wait_ms) M.org_imports = function(wait_ms)
@ -97,23 +127,18 @@ M.goimport = function(...)
local args = { ... } local args = { ... }
if _GO_NVIM_CFG.goimport == "gopls" then if _GO_NVIM_CFG.goimport == "gopls" then
if vim.fn.empty(args) == 1 then if vim.fn.empty(args) == 1 then
M.org_imports(1000) return M.org_imports(1000)
return
else else
local path = select(1, ...) local path = select(1, ...)
local gopls = require("go.gopls") local gopls = require("go.gopls")
gopls.import(path) return gopls.import(path)
return
end end
end end
local a1 = select(1, args) local a1 = select(1, args)
local buf = true local buf = vim.api.nvim_get_current_buf()
if #args > 0 and type(args[1]) == "boolean" then
buf = a1
table.remove(args, 1)
end
require("go.install").install(goimport) require("go.install").install(goimport)
if #args > 0 and _GO_NVIM_CFG.goimport == "goimports" then -- dont use golines -- specified the pkg name
if #args > 0 then -- dont use golines
return run(args, buf, "goimports") return run(args, buf, "goimports")
end end

@ -98,8 +98,10 @@ local function run_test(path, args)
log(tags) log(tags)
local cmd = {} local cmd = {}
if _GO_NVIM_CFG.run_in_floaterm then
table.insert(cmd, test_runner) local run_in_floaterm = optarg["F"] or _GO_NVIM_CFG.run_in_floaterm
if run_in_floaterm then
table.insert(cmd, test_runner or "go")
table.insert(cmd, "test") table.insert(cmd, "test")
end end
@ -134,7 +136,7 @@ local function run_test(path, args)
end end
end end
utils.log(cmd, args) utils.log(cmd, args)
if _GO_NVIM_CFG.run_in_floaterm then if run_in_floaterm then
local term = require("go.term").run local term = require("go.term").run
term({ cmd = cmd, autoclose = false }) term({ cmd = cmd, autoclose = false })
return cmd return cmd
@ -263,6 +265,7 @@ M.test_file = function(...)
-- require sed -- require sed
-- local testcases = [[sed -n 's/func.*\(Test.*\)(.*/\1/p' | xargs | sed 's/ /\\\|/g']] -- local testcases = [[sed -n 's/func.*\(Test.*\)(.*/\1/p' | xargs | sed 's/ /\\\|/g']]
-- local fpath = vim.fn.expand("%:p") -- local fpath = vim.fn.expand("%:p")
local fpath = "." .. sep .. vim.fn.fnamemodify(vim.fn.expand("%:p"), ":~:.") local fpath = "." .. sep .. vim.fn.fnamemodify(vim.fn.expand("%:p"), ":~:.")
-- utils.log(args) -- utils.log(args)
local cmd = [[cat ]] .. fpath .. [[| sed -n 's/func.*\(Test.*\)(.*/\1/p' | xargs | sed 's/ /\|/g']] local cmd = [[cat ]] .. fpath .. [[| sed -n 's/func.*\(Test.*\)(.*/\1/p' | xargs | sed 's/ /\|/g']]
@ -295,7 +298,8 @@ M.test_file = function(...)
end end
end end
local relpath = utils.rel_path() local relpath = utils.rel_path(true)
log(relpath)
local cmd_args = {} local cmd_args = {}
if run_in_floaterm then if run_in_floaterm then
@ -325,6 +329,7 @@ M.test_file = function(...)
end end
vim.cmd([[setl makeprg=]] .. _GO_NVIM_CFG.go .. [[\ test]]) vim.cmd([[setl makeprg=]] .. _GO_NVIM_CFG.go .. [[\ test]])
log (cmd_args)
local cmdret = require("go.asyncmake").make(unpack(cmd_args)) local cmdret = require("go.asyncmake").make(unpack(cmd_args))

@ -1,4 +1,5 @@
local util = {} local util = {}
local fn = vim.fn
local os_name = vim.loop.os_uname().sysname local os_name = vim.loop.os_uname().sysname
local is_windows = os_name == "Windows" or os_name == "Windows_NT" local is_windows = os_name == "Windows" or os_name == "Windows_NT"
@ -35,14 +36,14 @@ end
function util.root_dirs() function util.root_dirs()
local dirs = {} local dirs = {}
local root = vim.fn.systemlist({ _GO_NVIM_CFG.go, "env", "GOROOT" }) local root = fn.systemlist({ _GO_NVIM_CFG.go, "env", "GOROOT" })
table.insert(dirs, root[1]) table.insert(dirs, root[1])
local paths = vim.fn.systemlist({ _GO_NVIM_CFG.go, "env", "GOPATH" }) local paths = fn.systemlist({ _GO_NVIM_CFG.go, "env", "GOPATH" })
local sp = get_path_sep() local sp = get_path_sep()
paths = vim.split(paths[1], sp) paths = vim.split(paths[1], sp)
for _, p in pairs(paths) do for _, p in pairs(paths) do
p = vim.fn.substitute(p, "\\\\", "/", "g") p = fn.substitute(p, "\\\\", "/", "g")
table.insert(dirs, p) table.insert(dirs, p)
end end
return dirs return dirs
@ -53,9 +54,9 @@ function util.go_packages(dirs, arglead)
local pkgs = {} local pkgs = {}
for _, dir in pairs(dirs) do for _, dir in pairs(dirs) do
util.log(dir) util.log(dir)
local scr_root = vim.fn.expand(dir .. util.sep() .. "src" .. util.sep()) local scr_root = fn.expand(dir .. util.sep() .. "src" .. util.sep())
util.log(scr_root, arglead) util.log(scr_root, arglead)
local roots = vim.fn.globpath(scr_root, arglead .. "*", 0, 1) local roots = fn.globpath(scr_root, arglead .. "*", 0, 1)
if roots == { "" } then if roots == { "" } then
roots = {} roots = {}
end end
@ -64,7 +65,7 @@ function util.go_packages(dirs, arglead)
for _, pkg in pairs(roots) do for _, pkg in pairs(roots) do
util.log(pkg) util.log(pkg)
if vim.fn.isdirectory(pkg) then if fn.isdirectory(pkg) then
pkg = pkg .. util.sep() pkg = pkg .. util.sep()
table.insert(pkgs, pkg) table.insert(pkgs, pkg)
elseif not pkg:match([[%.a$]]) then elseif not pkg:match([[%.a$]]) then
@ -73,7 +74,7 @@ function util.go_packages(dirs, arglead)
pkg = strip_path_sep(pkg) pkg = strip_path_sep(pkg)
-- remove the scr root and keep the package in tact -- remove the scr root and keep the package in tact
pkg = vim.fn.substitute(pkg, scr_root, "", "") pkg = fn.substitute(pkg, scr_root, "", "")
table.insert(pkgs, pkg) table.insert(pkgs, pkg)
end end
end end
@ -94,7 +95,7 @@ end
-- endfunction -- endfunction
function util.interface_list(pkg) function util.interface_list(pkg)
local p = vim.fn.systemlist({ _GO_NVIM_CFG.go, "doc", pkg }) local p = fn.systemlist({ _GO_NVIM_CFG.go, "doc", pkg })
util.log(p) util.log(p)
local ifaces = {} local ifaces = {}
if p then if p then
@ -102,7 +103,7 @@ function util.interface_list(pkg)
for _, content in pairs(contents) do for _, content in pairs(contents) do
util.log(content) util.log(content)
if content:find("interface") then if content:find("interface") then
local iface_name = vim.fn.matchstr(content, [[^type\s\+\zs\h\w*\ze\s\+interface]]) local iface_name = fn.matchstr(content, [[^type\s\+\zs\h\w*\ze\s\+interface]])
if iface_name ~= "" then if iface_name ~= "" then
table.insert(ifaces, pkg .. iface_name) table.insert(ifaces, pkg .. iface_name)
end end
@ -204,7 +205,7 @@ util.handle_job_data = function(data)
return data return data
end end
local cache_dir = vim.fn.stdpath("cache") local cache_dir = fn.stdpath("cache")
util.log = function(...) util.log = function(...)
if not _GO_NVIM_CFG then if not _GO_NVIM_CFG then
return return
@ -339,7 +340,7 @@ function util.load_plugin(name, modulename)
end end
if packer_plugins ~= nil then if packer_plugins ~= nil then
-- packer installed -- packer installed
local has_packer = pcall(require, 'packer') local has_packer = pcall(require, "packer")
if not has_packer then if not has_packer then
error("packer not found") error("packer not found")
return nil return nil
@ -396,7 +397,7 @@ end
-- end -- end
function util.relative_to_cwd(name) function util.relative_to_cwd(name)
local rel = vim.fn.isdirectory(name) == 0 and vim.fn.fnamemodify(name, ":h:.") or vim.fn.fnamemodify(name, ":.") local rel = fn.isdirectory(name) == 0 and vim.fn.fnamemodify(name, ":h:.") or vim.fn.fnamemodify(name, ":.")
if rel == "." then if rel == "." then
return "." return "."
else else
@ -421,15 +422,19 @@ function util.info(msg)
vim.notify("INF: " .. msg, vim.lsp.log_levels.INFO) vim.notify("INF: " .. msg, vim.lsp.log_levels.INFO)
end end
function util.rel_path() function util.rel_path(folder)
local fpath = vim.fn.expand("%:p:h") local mod = "%:p"
if folder then
mod = "%:p:h"
end
local fpath = fn.expand(mod)
local workfolders = vim.lsp.buf.list_workspace_folders() local workfolders = vim.lsp.buf.list_workspace_folders()
if workfolders ~= nil and next(workfolders) then if workfolders ~= nil and next(workfolders) then
fpath = "." .. fpath:sub(#workfolders[1] + 1) fpath = "." .. fpath:sub(#workfolders[1] + 1)
end end
return "." .. util.sep() .. vim.fn.fnamemodify(vim.fn.expand("%:p"), ":~:.") return "." .. util.sep() .. fn.fnamemodify(vim.fn.expand(mod), ":~:.")
end end
function util.rtrim(s) function util.rtrim(s)
@ -455,7 +460,7 @@ function util.file_exists(name)
end end
function util.work_path() function util.work_path()
local fpath = vim.fn.expand("%:p:h") local fpath = fn.expand("%:p:h")
local workfolders = vim.lsp.buf.list_workspace_folders() local workfolders = vim.lsp.buf.list_workspace_folders()
if #workfolders == 1 then if #workfolders == 1 then
return workfolders[1] return workfolders[1]
@ -525,14 +530,18 @@ end
function util.file_exists(file) function util.file_exists(file)
local f = io.open(file, "rb") local f = io.open(file, "rb")
if f then f:close() end if f then
f:close()
end
return f ~= nil return f ~= nil
end end
-- get all lines from a file, returns an empty -- get all lines from a file, returns an empty
-- list/table if the file does not exist -- list/table if the file does not exist
function util.lines_from(file) function util.lines_from(file)
if not util.file_exists(file) then return {} end if not util.file_exists(file) then
return {}
end
local lines = {} local lines = {}
for line in io.lines(file) do for line in io.lines(file) do
lines[#lines + 1] = line lines[#lines + 1] = line
@ -540,19 +549,35 @@ function util.lines_from(file)
return lines return lines
end end
function util.set_env(key, val) function util.list_directory()
local dirs = fn.map(fn.glob(fn.fnameescape("./") .. "/{,.}*/", 1, 1), 'fnamemodify(v:val, ":h:t")')
end end
function util.list_directory() function util.get_active_buf()
local fn = vim.fn local lb = fn.getbufinfo({ buflisted = 1 })
local dirs = fn.map(fn.glob(fn.fnameescape('./')..'/{,.}*/', 1, 1), 'fnamemodify(v:val, ":h:t")') util.log(lb)
local result = {}
for _, item in ipairs(lb) do
if fn.empty(item.name) == 0 and item.hidden == 0 then
util.log("buf loaded", item.name)
table.insert(result, { name = fn.shellescape(item.name), bufnr = item.bufnr })
end
end
return result
end end
-- for l:item in l:blist
-- "skip unnamed buffers; also skip hidden buffers?
-- if empty(l:item.name) || l:item.hidden
-- continue
-- endif
-- call add(l:result, shellescape(l:item.name))
-- return l:result
function util.set_nulls() function util.set_nulls()
if _GO_NVIM_CFG.null_ls_document_formatting_disable then if _GO_NVIM_CFG.null_ls_document_formatting_disable then
local query = {} local query = {}
if type( _GO_NVIM_CFG.null_ls_document_formatting_disable) ~= 'boolean' if type(_GO_NVIM_CFG.null_ls_document_formatting_disable) ~= "boolean" then
then
query = _GO_NVIM_CFG.null_ls_document_formatting_disable query = _GO_NVIM_CFG.null_ls_document_formatting_disable
end end
local ok, nulls = pcall(require, "null-ls") local ok, nulls = pcall(require, "null-ls")

@ -56,7 +56,7 @@ describe("should run gofmt", function()
print("tmp" .. name) print("tmp" .. name)
local gofmt = require("go.format") local gofmt = require("go.format")
gofmt.gofmt(true) gofmt.gofmt()
-- enable the channel response -- enable the channel response
vim.wait(400, function() end) vim.wait(400, function() end)
local fmt = vim.fn.join(vim.fn.readfile(name), "\n") local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
@ -85,7 +85,7 @@ describe("should run gofmt", function()
cmd = "bd! " .. name cmd = "bd! " .. name
vim.cmd(cmd) vim.cmd(cmd)
end) end)
it("should run import from file buffer with goimport", function() it("should run import from file with goimport with package name", function()
local path = cur_dir .. "/lua/tests/fixtures/fmt/goimports.go" -- %:p:h ? %:p 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 expected = vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/fmt/goimports_golden.go"), "\n")
local name = vim.fn.tempname() .. ".go" local name = vim.fn.tempname() .. ".go"
@ -97,9 +97,9 @@ describe("should run gofmt", function()
vim.cmd([[cd %:p:h]]) vim.cmd([[cd %:p:h]])
print("code write to " .. name) print("code write to " .. name)
require("go").setup({ goimport = "goimports" }) require("go").setup({ goimport = "goimports", gofmt = "gofmt" })
local gofmt = require("go.format") local gofmt = require("go.format")
gofmt.goimport(true) gofmt.goimport("fmt")
vim.wait(400, function() end) vim.wait(400, function() end)
vim.cmd([[w]]) vim.cmd([[w]])

Loading…
Cancel
Save