b9f161c18e
gomvp minor fix command auto complete
853 lines
20 KiB
Lua
853 lines
20 KiB
Lua
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'
|
|
-- Check whether current buffer contains main function
|
|
function util.has_main()
|
|
local output = vim.api.nvim_exec('grep func\\ main\\(\\) %', true)
|
|
local matchCount = vim.split(output, '\n')
|
|
|
|
return #matchCount > 3
|
|
end
|
|
|
|
function util.sep()
|
|
if is_windows then
|
|
return '\\'
|
|
end
|
|
return '/'
|
|
end
|
|
|
|
function util.sep2()
|
|
if is_windows then
|
|
return ';'
|
|
end
|
|
return ':'
|
|
end
|
|
|
|
function util.is_windows()
|
|
return is_windows
|
|
end
|
|
|
|
function util.ext()
|
|
if is_windows then
|
|
return '.exe'
|
|
end
|
|
return ''
|
|
end
|
|
local function get_path_sep()
|
|
if is_windows then
|
|
return ';'
|
|
end
|
|
return ':'
|
|
end
|
|
|
|
local function strip_path_sep(path)
|
|
local l = path[#path]
|
|
util.log(l, util.sep(), path:sub(1, #path - 1))
|
|
if l == util.sep() then
|
|
return path:sub(1, #path - 1)
|
|
end
|
|
return path
|
|
end
|
|
|
|
function util.root_dirs()
|
|
local dirs = {}
|
|
local root = fn.systemlist({ _GO_NVIM_CFG.go, 'env', 'GOROOT' })
|
|
table.insert(dirs, root[1])
|
|
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 = fn.substitute(p, '\\\\', '/', 'g')
|
|
table.insert(dirs, p)
|
|
end
|
|
return dirs
|
|
end
|
|
|
|
function util.go_packages(dirs, arglead)
|
|
util.log(debug.traceback())
|
|
local pkgs = {}
|
|
for _, dir in pairs(dirs) do
|
|
util.log(dir)
|
|
local scr_root = fn.expand(dir .. util.sep() .. 'src' .. util.sep())
|
|
util.log(scr_root, arglead)
|
|
local roots = fn.globpath(scr_root, arglead .. '*', 0, 1)
|
|
if roots == { '' } then
|
|
roots = {}
|
|
end
|
|
|
|
util.log(roots)
|
|
for _, pkg in pairs(roots) do
|
|
util.log(pkg)
|
|
|
|
if fn.isdirectory(pkg) then
|
|
pkg = pkg .. util.sep()
|
|
table.insert(pkgs, pkg)
|
|
elseif not pkg:match([[%.a$]]) then
|
|
-- without this the result can have duplicates in form of
|
|
-- 'encoding/json' and '/encoding/json/'
|
|
pkg = strip_path_sep(pkg)
|
|
|
|
-- remove the scr root and keep the package in tact
|
|
pkg = fn.substitute(pkg, scr_root, '', '')
|
|
table.insert(pkgs, pkg)
|
|
end
|
|
end
|
|
end
|
|
util.log(pkgs)
|
|
return pkgs
|
|
end
|
|
|
|
-- function! s:interface_list(pkg) abort
|
|
-- let [contents, err] = go#util#Exec(['go', 'doc', a:pkg])
|
|
-- if err
|
|
-- return []
|
|
-- endif
|
|
--
|
|
-- let contents = split(contents, "\n")
|
|
-- call filter(contents, 'v:val =~# ''^type\s\+\h\w*\s\+interface''')
|
|
-- return map(contents, 'a:pkg . "." . matchstr(v:val, ''^type\s\+\zs\h\w*\ze\s\+interface'')')
|
|
-- endfunction
|
|
|
|
function util.interface_list(pkg)
|
|
local p = fn.systemlist({ _GO_NVIM_CFG.go, 'doc', pkg })
|
|
util.log(p)
|
|
local ifaces = {}
|
|
if p then
|
|
local contents = p -- vim.split(p[1], "\n")
|
|
for _, content in pairs(contents) do
|
|
util.log(content)
|
|
if content:find('interface') then
|
|
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
|
|
end
|
|
end
|
|
end
|
|
util.log(ifaces)
|
|
return ifaces
|
|
end
|
|
|
|
-- https://alpha2phi.medium.com/neovim-101-regular-expression-f15a6d782add
|
|
function util.get_fname_num(line)
|
|
line = util.trim(line)
|
|
|
|
local reg = [[\(.\+\.go\)\:\(\d\+\):]]
|
|
local f = fn.matchlist(line, reg)
|
|
if f[1] and f[1] ~= '' then
|
|
return f[2], tonumber(f[3])
|
|
end
|
|
end
|
|
|
|
function util.smartrun()
|
|
local cmd
|
|
if util.has_main() then
|
|
cmd = string.format('lcd %:p:h | :set makeprg=%s\\ run\\ . | :make | :lcd -', _GO_NVIM_CFG.go)
|
|
vim.cmd(cmd)
|
|
else
|
|
cmd = string.format('setl makeprg=%s\\ run\\ . | :make', _GO_NVIM_CFG.go)
|
|
vim.cmd(cmd)
|
|
end
|
|
end
|
|
|
|
function util.smartbuild()
|
|
local cmd
|
|
if util.has_main() then
|
|
cmd = string.format('lcd %:p:h | :set makeprg=%s\\ build\\ . | :make | :lcd -', _GO_NVIM_CFG.go)
|
|
vim.cmd(cmd)
|
|
else
|
|
cmd = string.format('setl makeprg=%s\\ build\\ . | :make', _GO_NVIM_CFG.go)
|
|
vim.cmd(cmd)
|
|
end
|
|
end
|
|
|
|
util.check_same = function(tbl1, tbl2)
|
|
if #tbl1 ~= #tbl2 then
|
|
return false
|
|
end
|
|
for k, v in ipairs(tbl1) do
|
|
if v ~= tbl2[k] then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
util.map = function(modes, key, result, options)
|
|
options = util.merge({ noremap = true, silent = false, expr = false, nowait = false }, options or {})
|
|
local buffer = options.buffer
|
|
options.buffer = nil
|
|
|
|
if type(modes) ~= 'table' then
|
|
modes = { modes }
|
|
end
|
|
|
|
for i = 1, #modes do
|
|
if buffer then
|
|
vim.api.nvim_buf_set_keymap(0, modes[i], key, result, options)
|
|
else
|
|
vim.api.nvim_set_keymap(modes[i], key, result, options)
|
|
end
|
|
end
|
|
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.handle_job_data = function(data)
|
|
if not data then
|
|
return nil
|
|
end
|
|
-- Because the nvim.stdout's data will have an extra empty line at end on some OS (e.g. maxOS), we should remove it.
|
|
for _ = 1, 3, 1 do
|
|
if data[#data] == '' then
|
|
table.remove(data, #data)
|
|
end
|
|
end
|
|
if #data < 1 then
|
|
return nil
|
|
end
|
|
return data
|
|
end
|
|
|
|
local cache_dir = fn.stdpath('cache')
|
|
util.log = function(...)
|
|
if not _GO_NVIM_CFG or not _GO_NVIM_CFG.verbose then
|
|
return
|
|
end
|
|
local arg = { ... }
|
|
|
|
local log_default = string.format('%s%sgonvim.log', cache_dir, util.sep())
|
|
|
|
local log_path = _GO_NVIM_CFG.log_path or log_default
|
|
local str = ' '
|
|
|
|
local info = debug.getinfo(2, 'Sl')
|
|
str = str .. info.short_src .. ':' .. info.currentline
|
|
for i, v in ipairs(arg) do
|
|
if type(v) == 'table' then
|
|
str = str .. ' |' .. tostring(i) .. ': ' .. vim.inspect(v) .. '\n'
|
|
else
|
|
str = str .. ' |' .. tostring(i) .. ': ' .. tostring(v)
|
|
end
|
|
end
|
|
if #str > 2 then
|
|
if log_path ~= nil and #log_path > 3 then
|
|
local f, err = io.open(log_path, 'a+')
|
|
if err then
|
|
vim.notify('failed to open log' .. log_path .. err, vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
if not f then
|
|
error('open file ' .. log_path, f)
|
|
end
|
|
io.output(f)
|
|
io.write(str .. '\n')
|
|
io.close(f)
|
|
else
|
|
vim.notify(str .. '\n', vim.log.levels.DEBUG)
|
|
end
|
|
end
|
|
end
|
|
|
|
util.trace = function(...) end
|
|
|
|
local rhs_options = {}
|
|
|
|
function rhs_options:new()
|
|
local instance = {
|
|
cmd = '',
|
|
options = { noremap = false, silent = false, expr = false, nowait = false },
|
|
}
|
|
setmetatable(instance, self)
|
|
self.__index = self
|
|
return instance
|
|
end
|
|
|
|
function rhs_options:map_cmd(cmd_string)
|
|
self.cmd = cmd_string
|
|
return self
|
|
end
|
|
|
|
function rhs_options:map_cr(cmd_string)
|
|
self.cmd = (':%s<CR>'):format(cmd_string)
|
|
return self
|
|
end
|
|
|
|
function rhs_options:map_args(cmd_string)
|
|
self.cmd = (':%s<Space>'):format(cmd_string)
|
|
return self
|
|
end
|
|
|
|
function rhs_options:map_cu(cmd_string)
|
|
self.cmd = (':<C-u>%s<CR>'):format(cmd_string)
|
|
return self
|
|
end
|
|
|
|
function rhs_options:with_silent()
|
|
self.options.silent = true
|
|
return self
|
|
end
|
|
|
|
function rhs_options:with_noremap()
|
|
self.options.noremap = true
|
|
return self
|
|
end
|
|
|
|
function rhs_options:with_expr()
|
|
self.options.expr = true
|
|
return self
|
|
end
|
|
|
|
function rhs_options:with_nowait()
|
|
self.options.nowait = true
|
|
return self
|
|
end
|
|
|
|
function util.map_cr(cmd_string)
|
|
local ro = rhs_options:new()
|
|
return ro:map_cr(cmd_string)
|
|
end
|
|
|
|
function util.map_cmd(cmd_string)
|
|
local ro = rhs_options:new()
|
|
return ro:map_cmd(cmd_string)
|
|
end
|
|
|
|
function util.map_cu(cmd_string)
|
|
local ro = rhs_options:new()
|
|
return ro:map_cu(cmd_string)
|
|
end
|
|
|
|
function util.map_args(cmd_string)
|
|
local ro = rhs_options:new()
|
|
return ro:map_args(cmd_string)
|
|
end
|
|
|
|
function util.nvim_load_mapping(mapping)
|
|
for key, value in pairs(mapping) do
|
|
local mode, keymap = key:match('([^|]*)|?(.*)')
|
|
if type(value) == 'table' then
|
|
local rhs = value.cmd
|
|
local options = value.options
|
|
vim.api.nvim_set_keymap(mode, keymap, rhs, options)
|
|
end
|
|
end
|
|
end
|
|
|
|
function util.load_plugin(name, modulename)
|
|
assert(name ~= nil, 'plugin should not empty')
|
|
modulename = modulename or name
|
|
local has, plugin = pcall(require, modulename)
|
|
if has then
|
|
return plugin
|
|
end
|
|
local pkg = packer_plugins
|
|
|
|
local has_packer = pcall(require, 'packer')
|
|
local has_lazy = pcall(require, 'lazy')
|
|
if has_packer or has_lazy then
|
|
-- packer installed
|
|
if has_packer then
|
|
local loader = require('packer').loader
|
|
if not pkg[name] or not pkg[name].loaded then
|
|
util.log('packer loader ' .. name)
|
|
vim.cmd('packadd ' .. name) -- load with default
|
|
if pkg[name] ~= nil then
|
|
loader(name)
|
|
end
|
|
end
|
|
else
|
|
require('lazy').load({plugins =name})
|
|
end
|
|
else
|
|
util.log('packadd ' .. name)
|
|
local paths = vim.o.runtimepath
|
|
if paths:find(name) then
|
|
vim.cmd('packadd ' .. name)
|
|
end
|
|
end
|
|
|
|
has, plugin = pcall(require, modulename)
|
|
if not has then
|
|
util.info('plugin ' .. name .. ' module ' .. modulename .. ' not loaded ')
|
|
return nil
|
|
end
|
|
return plugin
|
|
end
|
|
|
|
-- deprecated
|
|
-- function util.check_capabilities(feature, client_id)
|
|
-- local clients = vim.lsp.buf_get_clients(client_id or 0)
|
|
--
|
|
-- local supported_client = false
|
|
-- for _, client in pairs(clients) do
|
|
-- -- util.log(client.resolved_capabilities)
|
|
-- util.log(client.server_capabilities)
|
|
-- supported_client = client.resolved_capabilities[feature]
|
|
-- supported_client = client.resolved_capabilities[feature]
|
|
-- if supported_client then
|
|
-- break
|
|
-- end
|
|
-- end
|
|
--
|
|
-- if supported_client then
|
|
-- return true
|
|
-- else
|
|
-- if #clients == 0 then
|
|
-- util.log("LSP: no client attached")
|
|
-- else
|
|
-- util.log("LSP: server does not support " .. feature)
|
|
-- end
|
|
-- return false
|
|
-- end
|
|
-- end
|
|
|
|
function util.relative_to_cwd(name)
|
|
local rel = fn.isdirectory(name) == 0 and fn.fnamemodify(name, ':h:.') or fn.fnamemodify(name, ':.')
|
|
if rel == '.' then
|
|
return '.'
|
|
else
|
|
return '.' .. util.sep() .. rel
|
|
end
|
|
end
|
|
|
|
function util.chdir(dir)
|
|
if fn.exists('*chdir') then
|
|
return fn.chdir(dir)
|
|
end
|
|
|
|
local oldir = fn.getcwd()
|
|
local cd = 'cd'
|
|
if fn.exists('*haslocaldir') and fn.haslocaldir() then
|
|
cd = 'lcd'
|
|
vim.cmd(cd .. ' ' .. fn.fnameescape(dir))
|
|
return oldir
|
|
end
|
|
end
|
|
|
|
function util.all_pkgs()
|
|
return '.' .. util.sep() .. '...'
|
|
end
|
|
|
|
-- log and messages
|
|
function util.warn(msg)
|
|
vim.notify('WARN: ' .. msg, vim.log.levels.WARN)
|
|
end
|
|
|
|
function util.error(msg)
|
|
vim.notify('ERR: ' .. msg, vim.log.levels.ERROR)
|
|
end
|
|
|
|
function util.info(msg)
|
|
vim.notify('INF: ' .. msg, vim.log.levels.INFO)
|
|
end
|
|
|
|
function util.debug(msg)
|
|
vim.notify('DEBUG: ' .. msg, vim.log.levels.DEBUG)
|
|
end
|
|
|
|
function util.rel_path(folder)
|
|
-- maybe expand('%:p:h:t')
|
|
local mod = '%:p'
|
|
if folder then
|
|
mod = '%:p:h'
|
|
end
|
|
local fpath = fn.expand(mod)
|
|
|
|
local workfolders = vim.lsp.buf.list_workspace_folders()
|
|
|
|
if fn.empty(workfolders) == 0 then
|
|
fpath = '.' .. fpath:sub(#workfolders[1] + 1)
|
|
else
|
|
fpath = fn.fnamemodify(fn.expand(mod), ':p:.')
|
|
end
|
|
|
|
util.log(fpath:sub(#fpath), fpath, util.sep())
|
|
if fpath:sub(#fpath) == util.sep() then
|
|
fpath = fpath:sub(1, #fpath - 1)
|
|
util.log(fpath)
|
|
end
|
|
return fpath
|
|
end
|
|
|
|
function util.trim(s)
|
|
if s then
|
|
s = util.ltrim(s)
|
|
return util.rtrim(s)
|
|
end
|
|
end
|
|
|
|
function util.rtrim(s)
|
|
local n = #s
|
|
while n > 0 and s:find('^%s', n) do
|
|
n = n - 1
|
|
end
|
|
return s:sub(1, n)
|
|
end
|
|
|
|
function util.ltrim(s)
|
|
return (s:gsub('^%s*', ''))
|
|
end
|
|
|
|
function util.work_path()
|
|
local fpath = fn.expand('%:p:h')
|
|
local workfolders = vim.lsp.buf.list_workspace_folders()
|
|
if #workfolders == 1 then
|
|
return workfolders[1]
|
|
end
|
|
|
|
for _, value in pairs(workfolders) do
|
|
local mod = value .. util.sep() .. 'go.mod'
|
|
if util.file_exists(mod) then
|
|
return value
|
|
end
|
|
end
|
|
|
|
return workfolders[1] or fpath
|
|
end
|
|
|
|
function util.empty(t)
|
|
if t == nil then
|
|
return true
|
|
end
|
|
if type(t) ~= 'table' then
|
|
return false
|
|
end
|
|
return next(t) == nil
|
|
end
|
|
|
|
local open = io.open
|
|
|
|
function util.read_file(path)
|
|
local file = open(path, 'rb') -- r read mode and b binary mode
|
|
if not file then
|
|
return nil
|
|
end
|
|
local content = file:read('*a') -- *a or *all reads the whole file
|
|
file:close()
|
|
return content
|
|
end
|
|
|
|
function util.restart(cmd_args)
|
|
local old_lsp_clients = vim.lsp.get_active_clients()
|
|
local configs = require('lspconfig.configs')
|
|
for _, client in pairs(old_lsp_clients) do
|
|
if client.name == 'gopls' then
|
|
vim.lsp.stop_client(client.id)
|
|
end
|
|
end
|
|
|
|
if configs['gopls'] ~= nil then
|
|
vim.defer_fn(function()
|
|
configs['gopls'].launch()
|
|
end, 500)
|
|
end
|
|
end
|
|
|
|
util.deletedir = function(dir)
|
|
local lfs = require('lfs')
|
|
for file in lfs.dir(dir) do
|
|
local file_path = dir .. '/' .. file
|
|
if file ~= '.' and file ~= '..' then
|
|
if lfs.attributes(file_path, 'mode') == 'file' then
|
|
os.remove(file_path)
|
|
print('remove file', file_path)
|
|
elseif lfs.attributes(file_path, 'mode') == 'directory' then
|
|
print('dir', file_path)
|
|
util.deletedir(file_path)
|
|
end
|
|
end
|
|
end
|
|
lfs.rmdir(dir)
|
|
util.log('remove dir', dir)
|
|
end
|
|
|
|
function util.file_exists(name)
|
|
local f = io.open(name, 'r')
|
|
if f ~= nil then
|
|
io.close(f)
|
|
return true
|
|
end
|
|
return false
|
|
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
|
|
local lines = {}
|
|
for line in io.lines(file) do
|
|
lines[#lines + 1] = line
|
|
end
|
|
return lines
|
|
end
|
|
|
|
function util.list_directory()
|
|
return fn.map(fn.glob(fn.fnameescape('./') .. '/{,.}*/', 1, 1), 'fnamemodify(v:val, ":h:t")')
|
|
end
|
|
|
|
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
|
|
query = _GO_NVIM_CFG.null_ls_document_formatting_disable
|
|
end
|
|
local ok, nulls = pcall(require, 'null-ls')
|
|
if ok then
|
|
nulls.disable(query)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- run in current source code path
|
|
function util.exec_in_path(cmd, bufnr, ...)
|
|
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
|
local path = fn.fnamemodify(fn.bufname(bufnr), ':p:h')
|
|
local dir = util.chdir(path)
|
|
local result
|
|
if type(cmd) == 'function' then
|
|
result = cmd(bufnr, ...)
|
|
else
|
|
result = fn.systemlist(cmd, ...)
|
|
end
|
|
util.log(result)
|
|
util.chdir(dir)
|
|
return result
|
|
end
|
|
|
|
function util.line_ending()
|
|
if vim.o.fileformat == 'dos' then
|
|
return '\r\n'
|
|
elseif vim.o.fileformat == 'mac' then
|
|
return '\r'
|
|
end
|
|
return '\n'
|
|
end
|
|
|
|
function util.offset(line, col)
|
|
util.log(line, col)
|
|
if vim.o.encoding ~= 'utf-8' then
|
|
print('only utf-8 encoding is supported current encoding: ', vim.o.encoding)
|
|
end
|
|
return fn.line2byte(line) + col - 2
|
|
end
|
|
|
|
-- parse //+build integration unit
|
|
-- //go:build ci
|
|
function util.get_build_tags(buf)
|
|
local tags = {}
|
|
buf = buf or '%'
|
|
local pattern = [[^//\s*[+|(go:)]*build\s\+\(.\+\)]]
|
|
local cnt = vim.fn.getbufinfo(buf)[1]['linecount']
|
|
cnt = math.min(cnt, 10)
|
|
for i = 1, cnt do
|
|
local line = vim.fn.trim(vim.fn.getbufline(buf, i)[1])
|
|
if string.find(line, 'package') then
|
|
break
|
|
end
|
|
local t = vim.fn.substitute(line, pattern, [[\1]], '')
|
|
if t ~= line then -- tag found
|
|
t = vim.fn.substitute(t, [[ \+]], ',', 'g')
|
|
table.insert(tags, t)
|
|
end
|
|
end
|
|
if #tags > 0 then
|
|
return tags
|
|
end
|
|
end
|
|
|
|
-- a uuid
|
|
function util.uuid()
|
|
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9)))
|
|
local random = math.random
|
|
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
return string.gsub(template, '[xy]', function(c)
|
|
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
|
|
return string.format('%x', v)
|
|
end)
|
|
end
|
|
|
|
local lorem =
|
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
|
|
function util.lorem()
|
|
return lorem
|
|
end
|
|
|
|
function util.random_words(len)
|
|
local str = util.lorem()
|
|
local words = fn.split(str, ' ')
|
|
str = ''
|
|
for i = 1, len do
|
|
str = str .. ' ' .. words[math.random(#words)]
|
|
end
|
|
return str
|
|
end
|
|
|
|
function util.random_line()
|
|
local lines = vim.split(lorem, ', ')
|
|
return lines[math.random(#lines)] .. ','
|
|
end
|
|
|
|
function util.run_command(cmd, ...)
|
|
local result = fn.systemlist(cmd, ...)
|
|
return result
|
|
end
|
|
|
|
function util.quickfix(cmd)
|
|
if _GO_NVIM_CFG.trouble == true then
|
|
local ok, trouble = pcall(require, 'trouble')
|
|
if ok then
|
|
if cmd:find('copen') then
|
|
trouble.open('quickfix')
|
|
else
|
|
trouble.open('loclist')
|
|
end
|
|
else
|
|
vim.notify('trouble not found')
|
|
end
|
|
else
|
|
vim.cmd(cmd)
|
|
end
|
|
end
|
|
|
|
util.debounce = function(func, duration)
|
|
local timer = vim.loop.new_timer()
|
|
local function inner(args)
|
|
timer:stop()
|
|
timer:start(
|
|
duration,
|
|
0,
|
|
vim.schedule_wrap(function()
|
|
func(args)
|
|
end)
|
|
)
|
|
end
|
|
|
|
local group = vim.api.nvim_create_augroup('gonvim__CleanupLuvTimers', {})
|
|
vim.api.nvim_create_autocmd('VimLeavePre', {
|
|
group = group,
|
|
pattern = '*',
|
|
callback = function()
|
|
if timer then
|
|
if timer:has_ref() then
|
|
timer:stop()
|
|
if not timer:is_closing() then
|
|
timer:close()
|
|
end
|
|
end
|
|
timer = nil
|
|
end
|
|
end,
|
|
})
|
|
|
|
return timer, inner
|
|
end
|
|
|
|
local namepath = {}
|
|
|
|
util.extract_filepath = function(msg)
|
|
msg = msg or ''
|
|
-- util.log(msg)
|
|
--[[ or [[ findAllSubStr_test.go:234: Error inserting caseResult1: operation error DynamoDB: PutItem, exceeded maximum number of attempts]]
|
|
|
|
-- or 'path/path2/filename.go:50:11: Error invaild
|
|
-- or /home/ray/go/src/github/sample/app/driver.go:342 +0x19e5
|
|
local pos, _ = msg:find([[[%w_%-%./]+%.go:%d+:]])
|
|
if not pos then
|
|
pos, _ = msg:find([[[%w_%-%./]+%.go:%d+ ]]) -- test failure with panic
|
|
end
|
|
local pos2
|
|
if not pos then
|
|
return
|
|
end
|
|
pos2 = msg:find(':')
|
|
local s = msg:sub(1, pos2 - 1)
|
|
util.log('fname : ', s)
|
|
if vim.fn.filereadable(s) == 1 then
|
|
util.log('filename', s)
|
|
-- no need to extract path, already quickfix format
|
|
return
|
|
end
|
|
if not pos2 then
|
|
util.log('incorrect format', msg)
|
|
return
|
|
end
|
|
pos2 = msg:find(':')
|
|
local fname = msg:sub(pos, pos2 - 1)
|
|
util.log(fname, namepath[fname])
|
|
if namepath[fname] ~= nil then
|
|
return namepath[fname]
|
|
end
|
|
if vim.fn.filereadable(fname) == 1 then
|
|
return
|
|
end
|
|
if vim.fn.executable('find') == 0 then
|
|
return
|
|
end
|
|
-- note: slow operations
|
|
local cmd = 'find ./ -type f -name ' .. fname
|
|
local path = vim.fn.systemlist(cmd)
|
|
|
|
if vim.v.shell_error ~= 0 then
|
|
util.warn('find failed ' .. cmd .. vim.inspect(path))
|
|
return
|
|
end
|
|
for _, value in pairs(path) do
|
|
local st, _ = value:find(fname)
|
|
if st then
|
|
-- find cmd returns `./path/path2/filename.go`, the leading './' is not needed for quickfix
|
|
local p = value:sub(1, st - 1)
|
|
util.log(value, st, p)
|
|
namepath[st] = p
|
|
return p
|
|
end
|
|
end
|
|
end
|
|
|
|
return util
|