From eb4d380807913b2b4e7d4c81d5ab5aa745ea6ae6 Mon Sep 17 00:00:00 2001 From: ray-x Date: Thu, 26 May 2022 15:07:14 +1000 Subject: [PATCH] allow format all buffers with goimports --- README.md | 4 +- doc/go.txt | 6 +-- lua/go.lua | 2 +- lua/go/format.lua | 85 +++++++++++++++++++++++++-------------- lua/go/gotest.lua | 13 ++++-- lua/go/utils.lua | 73 ++++++++++++++++++++++----------- lua/tests/go_fmt_spec.lua | 8 ++-- 7 files changed, 124 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 08afc8f..4f67093 100644 --- a/README.md +++ b/README.md @@ -306,10 +306,12 @@ gofmt) | command | Description | | --------------------- | --------------------------- | -| GoFmt | goline + gofumpt | +| GoFmt {opts} | goline + gofumpt | | GoImport | goline + goimport + gofumpt | | GoImport package_path | gopls add_import package | +{opts} : ``-a`` format all buffers + ## GoImpl generate method stubs for implementing an interface diff --git a/doc/go.txt b/doc/go.txt index 9148f20..5a54615 100644 --- a/doc/go.txt +++ b/doc/go.txt @@ -164,7 +164,7 @@ COMMANDS *go-nvim-commands* au Syntax go hi goCoverageCovered guibg=green au Syntax go hi goCoverageUncover guibg=brown augroup end -:GoImport *:GoImport* +:GoImport {package_name} *:GoImport* Add, modify imports. :GoBuild {-tags=tagname}{pakcage_name} *:GoBuild* @@ -191,8 +191,8 @@ COMMANDS *go-nvim-commands* :GoAddTest *:GoAddTest* Add unit test for current function -:GoFmt {-tags=tagname}{pakcage_name} *:GoFmt* - Format code with golines+gofumpt package +:GoFmt {-a} *:GoFmt* + Format code with golines+gofumpt. -a: apply to all files :GoVet *:GoVet* Run go vet :GoCheat query *:GoCheat* diff --git a/lua/go.lua b/lua/go.lua index 3cce95f..6f0d912 100644 --- a/lua/go.lua +++ b/lua/go.lua @@ -91,7 +91,7 @@ function go.setup(cfg) 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({})]]) vim.cmd( [[command! -nargs=* -complete=custom,v:lua.package.loaded.go.doc_complete GoImport lua require("go.format").goimport()]] diff --git a/lua/go/format.lua b/lua/go/format.lua index bd9b154..8603b00 100644 --- a/lua/go/format.lua +++ b/lua/go/format.lua @@ -14,20 +14,28 @@ local gofmt_args = _GO_NVIM_CFG.gofmt_args or { local goimport_args = _GO_NVIM_CFG.goimport_args or { "--max-len=" .. tostring(max_len), - "--base-formatter=" .. goimport, + "--base-formatter=goimports", } -local run = function(fmtargs, from_buffer, cmd) - local args = vim.deepcopy(fmtargs) - if not from_buffer then - table.insert(args, api.nvim_buf_get_name(0)) - log("formatting buffer... " .. api.nvim_buf_get_name(0) .. vim.inspect(args), vim.lsp.log_levels.DEBUG) - else - log("formatting... " .. vim.inspect(args), vim.lsp.log_levels.DEBUG) +local run = function(fmtargs, bufnr, cmd) + log(fmtargs, bufnr, cmd) + bufnr = bufnr or 0 + if _GO_NVIM_CFG.gofmt == "gopls" then + if not vim.api.nvim_buf_is_loaded(bufnr) then + vim.fn.bufload(bufnr) + end + vim.lsp.buf.format({ async = true, bufnr = bufnr }) + return end - if vim.fn.getbufinfo('%')[1].changed == 1 then - api.nvim_command("w") + local args = vim.deepcopy(fmtargs) + 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 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 vim.notify("updating codes", vim.lsp.log_levels.DEBUG) api.nvim_buf_set_lines(0, 0, -1, false, data) - api.nvim_command("write") + vim.cmd("write") else vim.notify("already formatted", vim.lsp.log_levels.DEBUG) end @@ -62,7 +70,7 @@ local run = function(fmtargs, from_buffer, cmd) -- log(vim.inspect(data) .. "exit") -- log("current data " .. vim.inspect(new_lines)) old_lines = nil - vim.cmd('write') + vim.cmd("write") end, stdout_buffered = true, stderr_buffered = true, @@ -72,19 +80,41 @@ local run = function(fmtargs, from_buffer, cmd) end local M = {} -M.gofmt = function(buf) - if _GO_NVIM_CFG.gofmt == "gopls" then - -- log("gopls format") - vim.lsp.buf.format({ async = true }) - return - end +M.gofmt = function(...) + local long_opts = { + all = "a", + } + + 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" - 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("golines") local 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 M.org_imports = function(wait_ms) @@ -97,23 +127,18 @@ M.goimport = function(...) local args = { ... } if _GO_NVIM_CFG.goimport == "gopls" then if vim.fn.empty(args) == 1 then - M.org_imports(1000) - return + return M.org_imports(1000) else local path = select(1, ...) local gopls = require("go.gopls") - gopls.import(path) - return + return gopls.import(path) end end local a1 = select(1, args) - local buf = true - if #args > 0 and type(args[1]) == "boolean" then - buf = a1 - table.remove(args, 1) - end + local buf = vim.api.nvim_get_current_buf() 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") end diff --git a/lua/go/gotest.lua b/lua/go/gotest.lua index b4d7a0b..b333d93 100644 --- a/lua/go/gotest.lua +++ b/lua/go/gotest.lua @@ -98,8 +98,10 @@ local function run_test(path, args) log(tags) 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") end @@ -134,7 +136,7 @@ local function run_test(path, args) end end utils.log(cmd, args) - if _GO_NVIM_CFG.run_in_floaterm then + if run_in_floaterm then local term = require("go.term").run term({ cmd = cmd, autoclose = false }) return cmd @@ -263,6 +265,7 @@ M.test_file = function(...) -- require sed -- local testcases = [[sed -n 's/func.*\(Test.*\)(.*/\1/p' | xargs | sed 's/ /\\\|/g']] -- local fpath = vim.fn.expand("%:p") + local fpath = "." .. sep .. vim.fn.fnamemodify(vim.fn.expand("%:p"), ":~:.") -- utils.log(args) 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 - local relpath = utils.rel_path() + local relpath = utils.rel_path(true) + log(relpath) local cmd_args = {} if run_in_floaterm then @@ -325,6 +329,7 @@ M.test_file = function(...) end vim.cmd([[setl makeprg=]] .. _GO_NVIM_CFG.go .. [[\ test]]) + log (cmd_args) local cmdret = require("go.asyncmake").make(unpack(cmd_args)) diff --git a/lua/go/utils.lua b/lua/go/utils.lua index f87d917..ef80392 100644 --- a/lua/go/utils.lua +++ b/lua/go/utils.lua @@ -1,4 +1,5 @@ local util = {} +local fn = vim.fn local os_name = vim.loop.os_uname().sysname local is_windows = os_name == "Windows" or os_name == "Windows_NT" @@ -35,14 +36,14 @@ end function util.root_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]) - 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() paths = vim.split(paths[1], sp) for _, p in pairs(paths) do - p = vim.fn.substitute(p, "\\\\", "/", "g") + p = fn.substitute(p, "\\\\", "/", "g") table.insert(dirs, p) end return dirs @@ -53,9 +54,9 @@ function util.go_packages(dirs, arglead) local pkgs = {} for _, dir in pairs(dirs) do 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) - local roots = vim.fn.globpath(scr_root, arglead .. "*", 0, 1) + local roots = fn.globpath(scr_root, arglead .. "*", 0, 1) if roots == { "" } then roots = {} end @@ -64,7 +65,7 @@ function util.go_packages(dirs, arglead) for _, pkg in pairs(roots) do util.log(pkg) - if vim.fn.isdirectory(pkg) then + if fn.isdirectory(pkg) then pkg = pkg .. util.sep() table.insert(pkgs, pkg) elseif not pkg:match([[%.a$]]) then @@ -73,7 +74,7 @@ function util.go_packages(dirs, arglead) pkg = strip_path_sep(pkg) -- 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) end end @@ -94,7 +95,7 @@ end -- endfunction 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) local ifaces = {} if p then @@ -102,7 +103,7 @@ function util.interface_list(pkg) for _, content in pairs(contents) do util.log(content) 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 table.insert(ifaces, pkg .. iface_name) end @@ -204,7 +205,7 @@ util.handle_job_data = function(data) return data end -local cache_dir = vim.fn.stdpath("cache") +local cache_dir = fn.stdpath("cache") util.log = function(...) if not _GO_NVIM_CFG then return @@ -339,7 +340,7 @@ function util.load_plugin(name, modulename) end if packer_plugins ~= nil then -- packer installed - local has_packer = pcall(require, 'packer') + local has_packer = pcall(require, "packer") if not has_packer then error("packer not found") return nil @@ -396,7 +397,7 @@ end -- end 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 return "." else @@ -421,15 +422,19 @@ function util.info(msg) vim.notify("INF: " .. msg, vim.lsp.log_levels.INFO) end -function util.rel_path() - local fpath = vim.fn.expand("%:p:h") +function util.rel_path(folder) + local mod = "%:p" + if folder then + mod = "%:p:h" + end + local fpath = fn.expand(mod) local workfolders = vim.lsp.buf.list_workspace_folders() if workfolders ~= nil and next(workfolders) then fpath = "." .. fpath:sub(#workfolders[1] + 1) end - return "." .. util.sep() .. vim.fn.fnamemodify(vim.fn.expand("%:p"), ":~:.") + return "." .. util.sep() .. fn.fnamemodify(vim.fn.expand(mod), ":~:.") end function util.rtrim(s) @@ -455,7 +460,7 @@ function util.file_exists(name) end 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() if #workfolders == 1 then return workfolders[1] @@ -525,14 +530,18 @@ end function util.file_exists(file) local f = io.open(file, "rb") - if f then f:close() end + if f then + f:close() + end return f ~= nil end -- get all lines from a file, returns an empty -- list/table if the file does not exist 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 = {} for line in io.lines(file) do lines[#lines + 1] = line @@ -540,19 +549,35 @@ function util.lines_from(file) return lines 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 -function util.list_directory() - local fn = vim.fn - local dirs = fn.map(fn.glob(fn.fnameescape('./')..'/{,.}*/', 1, 1), 'fnamemodify(v:val, ":h:t")') +function util.get_active_buf() + local lb = fn.getbufinfo({ buflisted = 1 }) + 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 +-- 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() if _GO_NVIM_CFG.null_ls_document_formatting_disable then local query = {} - if type( _GO_NVIM_CFG.null_ls_document_formatting_disable) ~= 'boolean' - then + if type(_GO_NVIM_CFG.null_ls_document_formatting_disable) ~= "boolean" then query = _GO_NVIM_CFG.null_ls_document_formatting_disable end local ok, nulls = pcall(require, "null-ls") diff --git a/lua/tests/go_fmt_spec.lua b/lua/tests/go_fmt_spec.lua index 12968cd..266a134 100644 --- a/lua/tests/go_fmt_spec.lua +++ b/lua/tests/go_fmt_spec.lua @@ -56,7 +56,7 @@ describe("should run gofmt", function() print("tmp" .. name) local gofmt = require("go.format") - gofmt.gofmt(true) + gofmt.gofmt() -- enable the channel response vim.wait(400, function() end) local fmt = vim.fn.join(vim.fn.readfile(name), "\n") @@ -85,7 +85,7 @@ describe("should run gofmt", function() cmd = "bd! " .. name vim.cmd(cmd) 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 expected = vim.fn.join(vim.fn.readfile(cur_dir .. "/lua/tests/fixtures/fmt/goimports_golden.go"), "\n") local name = vim.fn.tempname() .. ".go" @@ -97,9 +97,9 @@ describe("should run gofmt", function() vim.cmd([[cd %:p:h]]) print("code write to " .. name) - require("go").setup({ goimport = "goimports" }) + require("go").setup({ goimport = "goimports", gofmt = "gofmt" }) local gofmt = require("go.format") - gofmt.goimport(true) + gofmt.goimport("fmt") vim.wait(400, function() end) vim.cmd([[w]])