2021-03-10 12:15:06 +00:00
local util = { }
2022-05-26 05:07:14 +00:00
local fn = vim.fn
2021-08-16 23:59:01 +00:00
2021-11-10 02:20:54 +00:00
local os_name = vim.loop . os_uname ( ) . sysname
2022-07-30 13:05:27 +00:00
local is_windows = os_name == ' Windows ' or os_name == ' Windows_NT '
2021-08-16 23:59:01 +00:00
-- Check whether current buffer contains main function
2022-06-01 11:29:13 +00:00
function util . has_main ( )
2022-07-30 13:05:27 +00:00
local output = vim.api . nvim_exec ( ' grep func \\ main \\ ( \\ ) % ' , true )
local matchCount = vim.split ( output , ' \n ' )
2021-08-16 23:59:01 +00:00
return # matchCount > 3
end
2021-11-10 02:20:54 +00:00
function util . sep ( )
if is_windows then
2022-07-30 13:05:27 +00:00
return ' \\ '
2021-11-10 02:20:54 +00:00
end
2022-07-30 13:05:27 +00:00
return ' / '
2021-11-10 02:20:54 +00:00
end
2022-07-27 04:50:39 +00:00
function util . sep2 ( )
if is_windows then
2022-07-30 13:05:27 +00:00
return ' ; '
2022-07-27 04:50:39 +00:00
end
2022-07-30 13:05:27 +00:00
return ' : '
2022-07-27 04:50:39 +00:00
end
2022-07-01 09:15:12 +00:00
function util . is_windows ( )
return is_windows
end
2022-07-27 16:19:42 +00:00
function util . ext ( )
if is_windows then
2022-07-30 13:05:27 +00:00
return ' .exe '
2022-07-27 16:19:42 +00:00
end
2022-07-30 13:05:27 +00:00
return ' '
2022-07-27 16:19:42 +00:00
end
2021-12-22 04:01:15 +00:00
local function get_path_sep ( )
if is_windows then
2022-07-30 13:05:27 +00:00
return ' ; '
2021-12-22 04:01:15 +00:00
end
2022-07-30 13:05:27 +00:00
return ' : '
2021-12-22 04:01:15 +00:00
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 = { }
2022-07-30 13:05:27 +00:00
local root = fn.systemlist ( { _GO_NVIM_CFG.go , ' env ' , ' GOROOT ' } )
2021-12-22 04:01:15 +00:00
table.insert ( dirs , root [ 1 ] )
2022-07-30 13:05:27 +00:00
local paths = fn.systemlist ( { _GO_NVIM_CFG.go , ' env ' , ' GOPATH ' } )
2021-12-22 04:01:15 +00:00
local sp = get_path_sep ( )
paths = vim.split ( paths [ 1 ] , sp )
for _ , p in pairs ( paths ) do
2022-07-30 13:05:27 +00:00
p = fn.substitute ( p , ' \\ \\ ' , ' / ' , ' g ' )
2021-12-22 04:01:15 +00:00
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 )
2022-07-30 13:05:27 +00:00
local scr_root = fn.expand ( dir .. util.sep ( ) .. ' src ' .. util.sep ( ) )
2021-12-22 04:01:15 +00:00
util.log ( scr_root , arglead )
2022-07-30 13:05:27 +00:00
local roots = fn.globpath ( scr_root , arglead .. ' * ' , 0 , 1 )
if roots == { ' ' } then
2021-12-22 04:01:15 +00:00
roots = { }
end
util.log ( roots )
for _ , pkg in pairs ( roots ) do
util.log ( pkg )
2022-05-26 05:07:14 +00:00
if fn.isdirectory ( pkg ) then
2021-12-22 04:01:15 +00:00
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
2022-07-30 13:05:27 +00:00
pkg = fn.substitute ( pkg , scr_root , ' ' , ' ' )
2021-12-22 04:01:15 +00:00
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 )
2022-07-30 13:05:27 +00:00
local p = fn.systemlist ( { _GO_NVIM_CFG.go , ' doc ' , pkg } )
2021-12-22 04:01:15 +00:00
util.log ( p )
local ifaces = { }
if p then
2022-06-01 11:29:13 +00:00
local contents = p -- vim.split(p[1], "\n")
2021-12-22 04:01:15 +00:00
for _ , content in pairs ( contents ) do
util.log ( content )
2022-07-30 13:05:27 +00:00
if content : find ( ' interface ' ) then
2022-05-26 05:07:14 +00:00
local iface_name = fn.matchstr ( content , [[^type\s\+\zs\h\w*\ze\s\+interface]] )
2022-07-30 13:05:27 +00:00
if iface_name ~= ' ' then
2021-12-22 04:01:15 +00:00
table.insert ( ifaces , pkg .. iface_name )
end
end
end
end
util.log ( ifaces )
return ifaces
end
2022-10-01 04:53:27 +00:00
-- 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
2022-06-01 11:29:13 +00:00
function util . smartrun ( )
2022-01-10 10:26:41 +00:00
local cmd
2022-06-01 11:29:13 +00:00
if util.has_main ( ) then
2022-07-30 13:05:27 +00:00
cmd = string.format ( ' lcd %:p:h | :set makeprg=%s \\ run \\ . | :make | :lcd - ' , _GO_NVIM_CFG.go )
2022-01-10 10:26:41 +00:00
vim.cmd ( cmd )
2021-08-16 23:59:01 +00:00
else
2022-07-30 13:05:27 +00:00
cmd = string.format ( ' setl makeprg=%s \\ run \\ . | :make ' , _GO_NVIM_CFG.go )
2022-01-10 10:26:41 +00:00
vim.cmd ( cmd )
2021-08-16 23:59:01 +00:00
end
end
2022-06-01 11:29:13 +00:00
function util . smartbuild ( )
2022-01-10 10:26:41 +00:00
local cmd
2022-06-01 11:29:13 +00:00
if util.has_main ( ) then
2022-07-30 13:05:27 +00:00
cmd = string.format ( ' lcd %:p:h | :set makeprg=%s \\ build \\ . | :make | :lcd - ' , _GO_NVIM_CFG.go )
2022-01-10 10:26:41 +00:00
vim.cmd ( cmd )
2021-08-16 23:59:01 +00:00
else
2022-07-30 13:05:27 +00:00
cmd = string.format ( ' setl makeprg=%s \\ build \\ . | :make ' , _GO_NVIM_CFG.go )
2022-01-10 10:26:41 +00:00
vim.cmd ( cmd )
2021-08-16 23:59:01 +00:00
end
end
2021-03-10 12:15:06 +00:00
util.check_same = function ( tbl1 , tbl2 )
if # tbl1 ~= # tbl2 then
2021-07-04 02:01:28 +00:00
return false
2021-03-10 12:15:06 +00:00
end
for k , v in ipairs ( tbl1 ) do
if v ~= tbl2 [ k ] then
2021-07-04 02:01:28 +00:00
return false
2021-03-10 12:15:06 +00:00
end
end
2021-07-04 02:01:28 +00:00
return true
2021-03-10 12:15:06 +00:00
end
2021-11-13 03:29:42 +00:00
util.map = function ( modes , key , result , options )
2023-02-19 04:50:27 +00:00
options =
util.merge ( { noremap = true , silent = false , expr = false , nowait = false } , options or { } )
2021-11-13 03:29:42 +00:00
local buffer = options.buffer
options.buffer = nil
2022-07-30 13:05:27 +00:00
if type ( modes ) ~= ' table ' then
2021-12-16 07:15:21 +00:00
modes = { modes }
2021-11-13 03:29:42 +00:00
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
2021-03-10 12:15:06 +00:00
util.copy_array = function ( from , to )
for i = 1 , # from do
2021-07-08 16:16:22 +00:00
to [ i ] = from [ i ]
2021-03-10 12:15:06 +00:00
end
end
2021-07-08 16:16:22 +00:00
util.deepcopy = function ( orig )
2021-07-07 05:10:06 +00:00
local orig_type = type ( orig )
local copy
2022-07-30 13:05:27 +00:00
if orig_type == ' table ' then
2021-07-08 16:16:22 +00:00
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 ) ) )
2021-07-07 05:10:06 +00:00
else -- number, string, boolean, etc
2021-07-08 16:16:22 +00:00
copy = orig
2021-07-07 05:10:06 +00:00
end
return copy
end
util.handle_job_data = function ( data )
if not data then
return nil
2021-03-10 12:15:06 +00:00
end
2021-07-07 05:10:06 +00:00
-- Because the nvim.stdout's data will have an extra empty line at end on some OS (e.g. maxOS), we should remove it.
2022-06-01 11:29:13 +00:00
for _ = 1 , 3 , 1 do
2022-07-30 13:05:27 +00:00
if data [ # data ] == ' ' then
2021-12-27 08:47:59 +00:00
table.remove ( data , # data )
end
2021-07-07 05:10:06 +00:00
end
if # data < 1 then
return nil
end
return data
end
2021-03-10 12:15:06 +00:00
2022-07-30 13:05:27 +00:00
local cache_dir = fn.stdpath ( ' cache ' )
2021-03-10 12:15:06 +00:00
util.log = function ( ... )
2023-01-19 01:26:14 +00:00
if not _GO_NVIM_CFG or not _GO_NVIM_CFG.verbose then
2021-08-24 04:53:37 +00:00
return
end
2021-12-16 07:15:21 +00:00
local arg = { ... }
2022-01-14 03:35:23 +00:00
2022-07-30 13:05:27 +00:00
local log_default = string.format ( ' %s%sgonvim.log ' , cache_dir , util.sep ( ) )
2021-08-23 02:24:48 +00:00
local log_path = _GO_NVIM_CFG.log_path or log_default
2022-07-30 13:05:27 +00:00
local str = ' '
2021-09-20 09:05:04 +00:00
2022-07-30 13:05:27 +00:00
local info = debug.getinfo ( 2 , ' Sl ' )
str = str .. info.short_src .. ' : ' .. info.currentline
2023-02-19 04:50:27 +00:00
local _ , ms = vim.loop . gettimeofday ( )
str = string.format ( ' [%s %d] %s ' , os.date ( ) , ms , str )
2021-08-24 04:53:37 +00:00
for i , v in ipairs ( arg ) do
2022-07-30 13:05:27 +00:00
if type ( v ) == ' table ' then
str = str .. ' | ' .. tostring ( i ) .. ' : ' .. vim.inspect ( v ) .. ' \n '
2021-08-24 04:53:37 +00:00
else
2022-07-30 13:05:27 +00:00
str = str .. ' | ' .. tostring ( i ) .. ' : ' .. tostring ( v )
2021-07-08 16:16:22 +00:00
end
2021-08-24 04:53:37 +00:00
end
if # str > 2 then
if log_path ~= nil and # log_path > 3 then
2022-07-30 13:05:27 +00:00
local f , err = io.open ( log_path , ' a+ ' )
2021-08-24 04:53:37 +00:00
if err then
2023-02-12 20:55:00 +00:00
vim.notify ( ' failed to open log ' .. log_path .. err , vim.log . levels.ERROR )
2021-08-24 04:53:37 +00:00
return
end
if not f then
2022-07-30 13:05:27 +00:00
error ( ' open file ' .. log_path , f )
2021-07-08 16:16:22 +00:00
end
2021-08-24 04:53:37 +00:00
io.output ( f )
2022-07-30 13:05:27 +00:00
io.write ( str .. ' \n ' )
2021-08-24 04:53:37 +00:00
io.close ( f )
else
2023-02-12 20:55:00 +00:00
vim.notify ( str .. ' \n ' , vim.log . levels.DEBUG )
2021-07-08 16:16:22 +00:00
end
2021-03-10 12:15:06 +00:00
end
end
2022-07-05 22:28:29 +00:00
util.trace = function ( ... ) end
2022-06-26 22:12:49 +00:00
2021-07-10 11:04:24 +00:00
local rhs_options = { }
function rhs_options : new ( )
local instance = {
2022-07-30 13:05:27 +00:00
cmd = ' ' ,
2021-12-16 07:15:21 +00:00
options = { noremap = false , silent = false , expr = false , nowait = false } ,
2021-07-10 11:04:24 +00:00
}
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 )
2022-07-30 13:05:27 +00:00
self.cmd = ( ' :%s<CR> ' ) : format ( cmd_string )
2021-07-10 11:04:24 +00:00
return self
end
function rhs_options : map_args ( cmd_string )
2022-07-30 13:05:27 +00:00
self.cmd = ( ' :%s<Space> ' ) : format ( cmd_string )
2021-07-10 11:04:24 +00:00
return self
end
function rhs_options : map_cu ( cmd_string )
2022-07-30 13:05:27 +00:00
self.cmd = ( ' :<C-u>%s<CR> ' ) : format ( cmd_string )
2021-07-10 11:04:24 +00:00
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
2022-07-30 13:05:27 +00:00
local mode , keymap = key : match ( ' ([^|]*)|?(.*) ' )
if type ( value ) == ' table ' then
2021-07-10 11:04:24 +00:00
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 )
2022-07-30 13:05:27 +00:00
assert ( name ~= nil , ' plugin should not empty ' )
2021-07-10 11:04:24 +00:00
modulename = modulename or name
local has , plugin = pcall ( require , modulename )
if has then
return plugin
end
2023-02-08 09:56:26 +00:00
local pkg = packer_plugins
local has_packer = pcall ( require , ' packer ' )
local has_lazy = pcall ( require , ' lazy ' )
if has_packer or has_lazy then
2021-07-10 11:04:24 +00:00
-- packer installed
2023-02-08 09:56:26 +00:00
if has_packer then
2023-02-19 04:50:27 +00:00
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
2022-01-18 21:14:02 +00:00
end
2023-02-08 09:56:26 +00:00
else
2023-02-19 04:50:27 +00:00
require ( ' lazy ' ) . load ( { plugins = name } )
2023-02-08 09:56:26 +00:00
end
2021-07-10 11:04:24 +00:00
else
2022-07-30 13:05:27 +00:00
util.log ( ' packadd ' .. name )
2022-05-24 11:14:40 +00:00
local paths = vim.o . runtimepath
2022-05-24 11:17:55 +00:00
if paths : find ( name ) then
2022-07-30 13:05:27 +00:00
vim.cmd ( ' packadd ' .. name )
2022-05-24 10:58:54 +00:00
end
2021-07-10 11:04:24 +00:00
end
has , plugin = pcall ( require , modulename )
2021-07-10 13:53:33 +00:00
if not has then
2022-07-30 13:05:27 +00:00
util.info ( ' plugin ' .. name .. ' module ' .. modulename .. ' not loaded ' )
2022-01-15 11:14:56 +00:00
return nil
2021-07-10 13:53:33 +00:00
end
2021-07-10 11:04:24 +00:00
return plugin
end
2022-04-24 11:03:38 +00:00
-- deprecated
2022-04-30 09:55:07 +00:00
-- 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
2021-08-23 02:24:48 +00:00
2021-11-13 03:29:42 +00:00
function util . relative_to_cwd ( name )
2023-02-19 04:50:27 +00:00
local rel = fn.isdirectory ( name ) == 0 and fn.fnamemodify ( name , ' :h:. ' )
or fn.fnamemodify ( name , ' :. ' )
2022-07-30 13:05:27 +00:00
if rel == ' . ' then
return ' . '
2021-11-13 03:29:42 +00:00
else
2022-07-30 13:05:27 +00:00
return ' . ' .. util.sep ( ) .. rel
2021-11-13 03:29:42 +00:00
end
end
2022-06-18 05:43:07 +00:00
function util . chdir ( dir )
2022-07-30 13:05:27 +00:00
if fn.exists ( ' *chdir ' ) then
2022-06-18 05:43:07 +00:00
return fn.chdir ( dir )
end
local oldir = fn.getcwd ( )
2022-07-30 13:05:27 +00:00
local cd = ' cd '
if fn.exists ( ' *haslocaldir ' ) and fn.haslocaldir ( ) then
cd = ' lcd '
vim.cmd ( cd .. ' ' .. fn.fnameescape ( dir ) )
2022-06-18 05:43:07 +00:00
return oldir
end
end
2021-11-13 03:29:42 +00:00
function util . all_pkgs ( )
2022-07-30 13:05:27 +00:00
return ' . ' .. util.sep ( ) .. ' ... '
2021-11-13 03:29:42 +00:00
end
2021-11-16 22:22:16 +00:00
-- log and messages
function util . warn ( msg )
2023-02-12 20:55:00 +00:00
vim.notify ( ' WARN: ' .. msg , vim.log . levels.WARN )
2021-11-16 22:22:16 +00:00
end
function util . error ( msg )
2023-02-12 20:55:00 +00:00
vim.notify ( ' ERR: ' .. msg , vim.log . levels.ERROR )
2021-11-16 22:22:16 +00:00
end
function util . info ( msg )
2023-02-12 20:55:00 +00:00
vim.notify ( ' INF: ' .. msg , vim.log . levels.INFO )
2021-11-16 22:22:16 +00:00
end
2022-07-06 17:57:26 +00:00
function util . debug ( msg )
2023-02-12 20:55:00 +00:00
vim.notify ( ' DEBUG: ' .. msg , vim.log . levels.DEBUG )
2022-07-06 17:57:26 +00:00
end
2022-05-26 05:07:14 +00:00
function util . rel_path ( folder )
2022-07-05 22:28:29 +00:00
-- maybe expand('%:p:h:t')
2022-07-30 13:05:27 +00:00
local mod = ' %:p '
2022-05-26 05:07:14 +00:00
if folder then
2022-07-30 13:05:27 +00:00
mod = ' %:p:h '
2022-05-26 05:07:14 +00:00
end
local fpath = fn.expand ( mod )
2022-05-10 01:03:15 +00:00
2021-12-16 07:15:21 +00:00
local workfolders = vim.lsp . buf.list_workspace_folders ( )
2022-07-05 22:28:29 +00:00
if fn.empty ( workfolders ) == 0 then
2022-07-30 13:05:27 +00:00
fpath = ' . ' .. fpath : sub ( # workfolders [ 1 ] + 1 )
2022-07-05 22:28:29 +00:00
else
2022-07-30 13:05:27 +00:00
fpath = fn.fnamemodify ( fn.expand ( mod ) , ' :p:. ' )
2022-07-05 22:28:29 +00:00
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 )
2021-11-23 23:13:40 +00:00
end
2022-07-05 22:28:29 +00:00
return fpath
2021-11-23 23:13:40 +00:00
end
2022-06-26 22:12:49 +00:00
function util . trim ( s )
if s then
s = util.ltrim ( s )
return util.rtrim ( s )
end
end
2021-12-02 06:44:22 +00:00
function util . rtrim ( s )
local n = # s
2022-07-30 13:05:27 +00:00
while n > 0 and s : find ( ' ^%s ' , n ) do
2021-12-02 06:44:22 +00:00
n = n - 1
end
return s : sub ( 1 , n )
end
2022-02-23 05:28:21 +00:00
function util . ltrim ( s )
2022-07-30 13:05:27 +00:00
return ( s : gsub ( ' ^%s* ' , ' ' ) )
2022-02-23 05:28:21 +00:00
end
2021-12-16 07:15:21 +00:00
function util . work_path ( )
2022-07-30 13:05:27 +00:00
local fpath = fn.expand ( ' %:p:h ' )
2021-12-16 07:15:21 +00:00
local workfolders = vim.lsp . buf.list_workspace_folders ( )
if # workfolders == 1 then
return workfolders [ 1 ]
end
for _ , value in pairs ( workfolders ) do
2022-07-30 13:05:27 +00:00
local mod = value .. util.sep ( ) .. ' go.mod '
2021-12-17 03:48:41 +00:00
if util.file_exists ( mod ) then
2021-12-16 07:15:21 +00:00
return value
end
end
return workfolders [ 1 ] or fpath
2021-12-11 03:44:15 +00:00
end
2021-12-29 14:33:24 +00:00
function util . empty ( t )
if t == nil then
return true
end
2022-07-30 13:05:27 +00:00
if type ( t ) ~= ' table ' then
2022-06-03 09:07:05 +00:00
return false
end
2021-12-29 14:33:24 +00:00
return next ( t ) == nil
end
2022-01-14 03:35:23 +00:00
local open = io.open
function util . read_file ( path )
2022-07-30 13:05:27 +00:00
local file = open ( path , ' rb ' ) -- r read mode and b binary mode
2022-01-14 03:35:23 +00:00
if not file then
return nil
end
2022-07-30 13:05:27 +00:00
local content = file : read ( ' *a ' ) -- *a or *all reads the whole file
2022-01-14 03:35:23 +00:00
file : close ( )
return content
end
2022-02-21 22:46:59 +00:00
function util . restart ( cmd_args )
2022-09-29 04:28:22 +00:00
local old_lsp_clients = vim.lsp . get_active_clients ( )
2022-07-30 13:05:27 +00:00
local configs = require ( ' lspconfig.configs ' )
2022-09-29 04:28:22 +00:00
for _ , client in pairs ( old_lsp_clients ) do
2022-10-01 04:53:27 +00:00
if client.name == ' gopls ' then
vim.lsp . stop_client ( client.id )
end
2022-09-29 04:28:22 +00:00
end
2022-10-01 04:53:27 +00:00
if configs [ ' gopls ' ] ~= nil then
2022-09-29 04:28:22 +00:00
vim.defer_fn ( function ( )
2022-10-01 04:53:27 +00:00
configs [ ' gopls ' ] . launch ( )
end , 500 )
2022-02-21 22:46:59 +00:00
end
end
2022-05-10 07:59:48 +00:00
util.deletedir = function ( dir )
2022-07-30 13:05:27 +00:00
local lfs = require ( ' lfs ' )
2022-05-10 07:59:48 +00:00
for file in lfs.dir ( dir ) do
2022-07-30 13:05:27 +00:00
local file_path = dir .. ' / ' .. file
if file ~= ' . ' and file ~= ' .. ' then
if lfs.attributes ( file_path , ' mode ' ) == ' file ' then
2022-05-10 07:59:48 +00:00
os.remove ( file_path )
2022-07-30 13:05:27 +00:00
print ( ' remove file ' , file_path )
elseif lfs.attributes ( file_path , ' mode ' ) == ' directory ' then
print ( ' dir ' , file_path )
2022-05-10 07:59:48 +00:00
util.deletedir ( file_path )
end
end
end
lfs.rmdir ( dir )
2022-07-30 13:05:27 +00:00
util.log ( ' remove dir ' , dir )
2022-05-10 07:59:48 +00:00
end
2022-06-01 11:29:13 +00:00
function util . file_exists ( name )
2022-07-30 13:05:27 +00:00
local f = io.open ( name , ' r ' )
2022-06-01 11:29:13 +00:00
if f ~= nil then
io.close ( f )
return true
2022-05-26 05:07:14 +00:00
end
2022-06-01 11:29:13 +00:00
return false
2022-05-13 09:27:02 +00:00
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function util . lines_from ( file )
2022-05-26 05:07:14 +00:00
if not util.file_exists ( file ) then
return { }
end
2022-05-13 09:27:02 +00:00
local lines = { }
for line in io.lines ( file ) do
lines [ # lines + 1 ] = line
end
return lines
end
2022-05-26 05:07:14 +00:00
function util . list_directory ( )
2022-07-30 13:05:27 +00:00
return fn.map ( fn.glob ( fn.fnameescape ( ' ./ ' ) .. ' /{,.}*/ ' , 1 , 1 ) , ' fnamemodify(v:val, ":h:t") ' )
2022-05-13 09:27:02 +00:00
end
2022-05-26 05:07:14 +00:00
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
2022-07-30 13:05:27 +00:00
util.log ( ' buf loaded ' , item.name )
2022-05-26 05:07:14 +00:00
table.insert ( result , { name = fn.shellescape ( item.name ) , bufnr = item.bufnr } )
end
end
return result
2022-05-13 09:27:02 +00:00
end
2022-05-26 05:07:14 +00:00
-- 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
2022-05-13 09:27:02 +00:00
function util . set_nulls ( )
if _GO_NVIM_CFG.null_ls_document_formatting_disable then
local query = { }
2022-07-30 13:05:27 +00:00
if type ( _GO_NVIM_CFG.null_ls_document_formatting_disable ) ~= ' boolean ' then
2022-05-13 09:27:02 +00:00
query = _GO_NVIM_CFG.null_ls_document_formatting_disable
end
2022-07-30 13:05:27 +00:00
local ok , nulls = pcall ( require , ' null-ls ' )
2022-05-13 09:27:02 +00:00
if ok then
nulls.disable ( query )
end
end
end
2022-06-15 04:11:10 +00:00
2022-06-18 05:43:07 +00:00
-- run in current source code path
2022-06-26 22:12:49 +00:00
function util . exec_in_path ( cmd , bufnr , ... )
bufnr = bufnr or vim.api . nvim_get_current_buf ( )
2022-07-30 13:05:27 +00:00
local path = fn.fnamemodify ( fn.bufname ( bufnr ) , ' :p:h ' )
2022-06-18 05:43:07 +00:00
local dir = util.chdir ( path )
local result
2022-07-30 13:05:27 +00:00
if type ( cmd ) == ' function ' then
2022-06-26 22:12:49 +00:00
result = cmd ( bufnr , ... )
2022-06-18 05:43:07 +00:00
else
result = fn.systemlist ( cmd , ... )
end
util.log ( result )
util.chdir ( dir )
return result
end
function util . line_ending ( )
2022-07-30 13:05:27 +00:00
if vim.o . fileformat == ' dos ' then
return ' \r \n '
elseif vim.o . fileformat == ' mac ' then
return ' \r '
2022-06-18 05:43:07 +00:00
end
2022-07-30 13:05:27 +00:00
return ' \n '
2022-06-18 05:43:07 +00:00
end
function util . offset ( line , col )
util.log ( line , col )
2022-07-30 13:05:27 +00:00
if vim.o . encoding ~= ' utf-8 ' then
print ( ' only utf-8 encoding is supported current encoding: ' , vim.o . encoding )
2022-06-18 05:43:07 +00:00
end
return fn.line2byte ( line ) + col - 2
end
2022-06-15 04:11:10 +00:00
-- parse //+build integration unit
2022-08-06 11:11:12 +00:00
-- //go:build ci
2022-06-15 04:11:10 +00:00
function util . get_build_tags ( buf )
local tags = { }
2022-07-30 13:05:27 +00:00
buf = buf or ' % '
2022-08-06 02:54:32 +00:00
local pattern = [[^//\s*[+|(go:)]*build\s\+\(.\+\)]]
2022-07-30 13:05:27 +00:00
local cnt = vim.fn . getbufinfo ( buf ) [ 1 ] [ ' linecount ' ]
2022-06-15 04:11:10 +00:00
cnt = math.min ( cnt , 10 )
for i = 1 , cnt do
local line = vim.fn . trim ( vim.fn . getbufline ( buf , i ) [ 1 ] )
2022-07-30 13:05:27 +00:00
if string.find ( line , ' package ' ) then
2022-06-15 04:11:10 +00:00
break
end
2022-07-30 13:05:27 +00:00
local t = vim.fn . substitute ( line , pattern , [[\1]] , ' ' )
2022-06-15 04:11:10 +00:00
if t ~= line then -- tag found
2022-07-30 13:05:27 +00:00
t = vim.fn . substitute ( t , [[ \+]] , ' , ' , ' g ' )
2022-06-15 04:11:10 +00:00
table.insert ( tags , t )
end
end
if # tags > 0 then
return tags
end
end
2022-07-11 13:32:06 +00:00
-- a uuid
function util . uuid ( )
2022-07-30 13:05:27 +00:00
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 )
2022-07-11 13:32:06 +00:00
end
2022-07-30 13:05:27 +00:00
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 '
2022-07-11 13:32:06 +00:00
function util . lorem ( )
2022-07-17 11:33:14 +00:00
return lorem
2022-07-11 13:32:06 +00:00
end
function util . random_words ( len )
local str = util.lorem ( )
2022-07-30 13:05:27 +00:00
local words = fn.split ( str , ' ' )
str = ' '
2022-07-11 13:32:06 +00:00
for i = 1 , len do
2022-07-30 13:05:27 +00:00
str = str .. ' ' .. words [ math.random ( # words ) ]
2022-07-11 13:32:06 +00:00
end
return str
end
2022-07-17 11:33:14 +00:00
function util . random_line ( )
2022-07-30 13:05:27 +00:00
local lines = vim.split ( lorem , ' , ' )
return lines [ math.random ( # lines ) ] .. ' , '
2022-07-17 11:33:14 +00:00
end
2022-07-11 13:32:06 +00:00
function util . run_command ( cmd , ... )
local result = fn.systemlist ( cmd , ... )
return result
end
2022-07-30 13:05:27 +00:00
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
2022-07-26 16:21:58 +00:00
util.debounce = function ( func , duration )
2022-07-26 02:39:41 +00:00
local timer = vim.loop . new_timer ( )
local function inner ( args )
timer : stop ( )
timer : start (
duration ,
0 ,
vim.schedule_wrap ( function ( )
2022-07-26 16:21:58 +00:00
func ( args )
2022-07-26 02:39:41 +00:00
end )
)
end
2022-07-30 13:05:27 +00:00
local group = vim.api . nvim_create_augroup ( ' gonvim__CleanupLuvTimers ' , { } )
vim.api . nvim_create_autocmd ( ' VimLeavePre ' , {
2022-07-26 02:39:41 +00:00
group = group ,
2022-07-30 13:05:27 +00:00
pattern = ' * ' ,
2022-07-26 02:39:41 +00:00
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
2023-01-15 09:24:48 +00:00
local namepath = { }
2023-02-19 04:50:27 +00:00
util.extract_filepath = function ( msg , pkg_path )
2023-01-27 04:06:32 +00:00
msg = msg or ' '
-- util.log(msg)
2023-01-15 09:24:48 +00:00
--[[ or [[ findAllSubStr_test.go:234: Error inserting caseResult1: operation error DynamoDB: PutItem, exceeded maximum number of attempts]]
2023-01-27 04:06:32 +00:00
-- or 'path/path2/filename.go:50:11: Error invaild
-- or /home/ray/go/src/github/sample/app/driver.go:342 +0x19e5
2023-02-19 04:50:27 +00:00
local ma = fn.matchlist ( msg , [[\v\s*(\w+.+\.go):(\d+):]] )
ma = ma or fn.matchlist ( msg , [[\v\s*(\w+.+\.go):(\d+)]] )
local filename , lnum
if ma [ 2 ] then
util.log ( ma )
filename = ma [ 2 ]
lnum = ma [ 3 ]
else
2023-01-27 04:06:32 +00:00
return
end
2023-02-19 04:50:27 +00:00
util.log ( ' fname : ' .. ( filename or ' nil ' ) .. ' : ' .. ( lnum or ' -1 ' ) )
if namepath [ filename ] then
-- if name is same, no need to update path
return ( namepath [ filename ] ~= filename ) , namepath [ filename ] , lnum
end
if vim.fn . filereadable ( filename ) == 1 then
util.log ( ' filename ' , filename )
2023-01-27 04:06:32 +00:00
-- no need to extract path, already quickfix format
2023-02-19 04:50:27 +00:00
namepath [ filename ] = filename
return false , filename , lnum
2023-01-27 04:06:32 +00:00
end
2023-02-19 04:50:27 +00:00
if pkg_path then
local pn = pkg_path : gsub ( ' %.%.%. ' , ' ' )
local fname = pn .. util.sep ( ) .. filename
if vim.fn . filereadable ( fname ) == 1 then
namepath [ filename ] = fname
util.log ( ' fname with pkg_name ' , fname )
return true , fname , lnum
end
2023-01-15 09:24:48 +00:00
end
2023-02-19 04:50:27 +00:00
local fname = fn.fnamemodify ( fn.expand ( ' %:h ' ) , ' :~:. ' ) .. util.sep ( ) .. ma [ 2 ]
2023-02-17 10:54:44 +00:00
util.log ( fname , namepath [ fname ] )
2023-02-01 21:53:54 +00:00
if vim.fn . filereadable ( fname ) == 1 then
2023-02-19 04:50:27 +00:00
namepath [ filename ] = fname
return true , fname , lnum
end
if namepath [ filename ] ~= nil then
util.log ( namepath [ filename ] )
return namepath [ filename ] , lnum
2023-01-15 09:24:48 +00:00
end
2023-01-27 04:06:32 +00:00
if vim.fn . executable ( ' find ' ) == 0 then
2023-02-19 04:50:27 +00:00
return false , fname , lnum
2023-01-15 09:24:48 +00:00
end
-- note: slow operations
2023-02-19 04:50:27 +00:00
local cmd = ' find ./ -type f -name ' .. filename
2023-01-15 09:24:48 +00:00
local path = vim.fn . systemlist ( cmd )
if vim.v . shell_error ~= 0 then
2023-01-27 04:06:32 +00:00
util.warn ( ' find failed ' .. cmd .. vim.inspect ( path ) )
2023-01-15 09:24:48 +00:00
end
for _ , value in pairs ( path ) do
2023-02-19 04:50:27 +00:00
local st , _ = value : find ( filename )
2023-01-15 09:24:48 +00:00
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 )
2023-02-19 04:50:27 +00:00
namepath [ filename ] = p
return true , p , lnum
2023-01-15 09:24:48 +00:00
end
end
2023-02-19 04:50:27 +00:00
-- nothing... we will not check this file again
namepath [ filename ] = filename
2023-01-15 09:24:48 +00:00
end
2021-03-10 12:15:06 +00:00
return util