You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
navigator.lua/lua/navigator/util.lua

560 lines
11 KiB
Lua

3 years ago
-- retreives data form file
-- and line to highlight
-- Some of function copied from https://github.com/RishabhRD/nvim-lsputils
2 years ago
local M = { log_path = vim.lsp.get_log_path() }
-- local is_windows = uv.os_uname().version:match("Windows")
local guihua = require('guihua.util')
local nvim_0_6_1
local nvim_0_8
local vfn = vim.fn
local api = vim.api
M.path_sep = function()
2 years ago
local is_win = vim.loop.os_uname().sysname:find('Windows')
if is_win then
2 years ago
return '\\'
else
2 years ago
return '/'
end
end
local path_sep = M.path_sep()
M.path_cur = function()
2 years ago
local is_win = vim.loop.os_uname().sysname:find('Windows')
if is_win then
2 years ago
return '.\\'
else
2 years ago
return './'
end
end
M.round = function(x)
return math.max(0, math.floor(x - 0.5))
end
3 years ago
function M.get_data_from_file(filename, startLine)
local displayLine
if startLine < 3 then
displayLine = startLine
startLine = 0
else
startLine = startLine - 2
displayLine = 2
end
2 years ago
local uri = 'file:///' .. filename
3 years ago
local bufnr = vim.uri_to_bufnr(uri)
if not api.nvim_buf_is_loaded(bufnr) then
vfn.bufload(bufnr)
end
local data = api.nvim_buf_get_lines(bufnr, startLine, startLine + 8, false)
3 years ago
if data == nil or vim.tbl_isempty(data) then
startLine = nil
else
local len = #data
startLine = startLine + 1
for i = 1, len, 1 do
2 years ago
data[i] = startLine .. ' ' .. data[i]
3 years ago
startLine = startLine + 1
end
end
2 years ago
return { data = data, line = displayLine }
3 years ago
end
2 years ago
function M.io_read(filename)
local f = io.open(filename, 'r')
if f == nil then
return nil
end
local content = f:read('*a') -- *a or *all reads the whole file
f:close()
return content
end
function M.rm_file(filename)
return os.remove(filename)
end
function M.file_exists(name)
local f = io.open(name, 'r')
if f ~= nil then
io.close(f)
return true
end
return false
end
3 years ago
M.merge = function(t1, t2)
for k, v in pairs(t2) do
t1[k] = v
end
return t1
end
M.map = function(modes, key, result, options)
2 years ago
options = M.merge({ noremap = true, silent = false, expr = false, nowait = false }, options or {})
3 years ago
local buffer = options.buffer
options.buffer = nil
2 years ago
if type(modes) ~= 'table' then
modes = { modes }
3 years ago
end
for i = 1, #modes do
if buffer then
api.nvim_buf_set_keymap(0, modes[i], key, result, options)
3 years ago
else
api.nvim_set_keymap(modes[i], key, result, options)
3 years ago
end
end
end
3 years ago
function M.get_base(path)
local len = #path
for i = len, 1, -1 do
if path:sub(i, i) == path_sep then
3 years ago
local ret = path:sub(i + 1, len)
return ret
end
end
end
local function getDir(path)
local data = {}
local len = #path
if len <= 1 then
return nil
end
local last_index = 1
for i = 2, len do
local cur_char = path:sub(i, i)
if cur_char == path_sep then
local my_data = path:sub(last_index + 1, i - 1)
table.insert(data, my_data)
last_index = i
3 years ago
end
end
return data
3 years ago
end
function M.get_relative_path(base_path, my_path)
local base_data = getDir(base_path)
2 years ago
if base_data == nil then
return
end
3 years ago
local my_data = getDir(my_path)
2 years ago
if my_data == nil then
return
end
3 years ago
local base_len = #base_data
local my_len = #my_data
if base_len > my_len then
return my_path
end
3 years ago
if base_data[1] ~= my_data[1] then
return my_path
end
3 years ago
local cur = 0
for i = 1, base_len do
if base_data[i] ~= my_data[i] then
break
end
3 years ago
cur = i
end
2 years ago
local data = ''
for i = cur + 1, my_len do
data = data .. my_data[i] .. path_sep
end
3 years ago
data = data .. M.get_base(my_path)
return data
end
M.log = function(...)
return { ... }
end
M.info = function(...)
return { ... }
end
M.trace = function(...)
return { ... }
end
M.warn = function(...)
return { ... }
end
M.error = function(...)
print(...)
end
3 years ago
local level = 'error'
function M.setup()
if _NgConfigValues.debug == true then
level = 'info'
elseif _NgConfigValues.debug == 'trace' then
level = 'trace'
2 years ago
end
local default_config = { use_console = false, use_file = true, level = level }
if _NgConfigValues.debug_console_output then
default_config.use_console = true
default_config.use_file = false
2 years ago
end
M._log = require('guihua.log').new(default_config, true)
if _NgConfigValues.debug then
-- add log to you lsp.log
M.trace = M._log.trace
M.info = M._log.info
M.warn = M._log.warn
M.error = M._log.error
M.log = M.info
2 years ago
end
end
3 years ago
function M.fmt(...)
M._log.fmt_info(...)
end
3 years ago
function M.split(inputstr, sep)
if sep == nil then
2 years ago
sep = '%s'
end
3 years ago
local t = {}
2 years ago
for str in string.gmatch(inputstr, '([^' .. sep .. ']+)') do
table.insert(t, str)
end
3 years ago
return t
end
function M.quickfix_extract(line)
-- check if it is a line of file pos been selected
local split = M.split
line = vim.trim(line)
2 years ago
local sep = split(line, ' ')
3 years ago
if #sep < 2 then
M.log(line)
return nil
end
2 years ago
sep = split(sep[1], ':')
3 years ago
if #sep < 3 then
M.log(line)
return nil
end
local location = {
2 years ago
uri = 'file:///' .. sep[1],
range = { start = { line = sep[2] - 3 > 0 and sep[2] - 3 or 1 } },
}
2 years ago
location.range['end'] = { line = sep[2] + 15 }
3 years ago
return location
end
function M.getArgs(inputstr)
2 years ago
local sep = '%s'
3 years ago
local t = {}
local cmd
2 years ago
for str in string.gmatch(inputstr, '([^' .. sep .. ']+)') do
3 years ago
if not cmd then
cmd = str
else
table.insert(t, str)
end
end
return cmd, t
end
function M.p(t)
vim.notify(vim.inspect(t), vim.log.levels.INFO)
end
3 years ago
function M.printError(msg)
2 years ago
vim.cmd('echohl ErrorMsg')
3 years ago
vim.cmd(string.format([[echomsg '%s']], msg))
2 years ago
vim.cmd('echohl None')
3 years ago
end
function M.reload()
vim.lsp.stop_client(vim.lsp.get_active_clients())
2 years ago
vim.cmd([[edit]])
3 years ago
end
function M.open_log()
local path = vim.lsp.get_log_path()
2 years ago
vim.cmd('edit ' .. path)
3 years ago
end
function table.pack(...)
2 years ago
return { n = select('#', ...), ... }
end
3 years ago
function M.show(...)
2 years ago
local string = ''
3 years ago
local args = table.pack(...)
for i = 1, args.n do
2 years ago
string = string .. tostring(args[i]) .. '\t'
end
3 years ago
2 years ago
return string .. '\n'
3 years ago
end
function M.split2(s, sep)
3 years ago
local fields = {}
2 years ago
sep = sep or ' '
local pattern = string.format('([^%s]+)', sep)
2 years ago
_ = string.gsub(s, pattern, function(c)
fields[#fields + 1] = c
end)
3 years ago
return fields
end
function M.trim_and_pad(txt)
local len = #txt
if len <= 1 then
return
end
local tab_en = txt[1] == '\t' or false
txt = vim.trim(txt)
if tab_en then
if len - txt > 2 then
return ' ' .. txt
end
if len - txt > 0 then
return ' ' .. txt
end
end
local rep = math.min(12, len - #txt)
return string.rep(' ', rep / 4) .. txt
end
M.open_file = function(filename)
api.nvim_command(string.format('e! %s', filename))
end
3 years ago
M.open_file_at = guihua.open_file_at
3 years ago
2 years ago
-- function M.exists(var)
-- for k, _ in pairs(_G) do
-- if k == var then
-- return true
-- end
-- end
-- end
3 years ago
2 years ago
local exclude_ft = { 'scrollbar', 'help', 'NvimTree' }
function M.exclude(fname)
for i = 1, #exclude_ft do
if string.find(fname, exclude_ft[i]) then
return true
end
end
return false
end
--- virtual text
-- name space search
local nss
local bufs
function M.set_virt_eol(bufnr, lnum, chunks, priority, id)
if nss == nil then
2 years ago
nss = api.nvim_create_namespace('navigator_search')
end
bufnr = bufnr == 0 and api.nvim_get_current_buf() or bufnr
bufs[bufnr] = true
-- id may be nil
2 years ago
return api.nvim_buf_set_extmark(bufnr, nss, lnum, -1, { id = id, virt_text = chunks, priority = priority })
end
function M.clear_buf(bufnr)
if not bufnr then
return
end
bufnr = bufnr == 0 and api.nvim_get_current_buf() or bufnr
if bufs[bufnr] then
if api.nvim_buf_is_valid(bufnr) then
api.nvim_buf_clear_namespace(bufnr, nss, 0, -1)
-- nvim_buf_del_extmark
end
bufs[bufnr] = nil
end
end
function M.clear_all_buf()
for bufnr in pairs(bufs) do
M.clear_buf(bufnr)
end
bufs = {}
end
function M.get_current_winid()
return api.nvim_get_current_win()
end
function M.nvim_0_6_1()
if nvim_0_6_1 ~= nil then
return nvim_0_6_1
end
nvim_0_6_1 = vfn.has('nvim-0.6.1') == 1
if nvim_0_6_1 == false then
M.warn('Please use navigator 0.3 version for neovim version < 0.6.1')
end
return nvim_0_6_1
end
function M.nvim_0_8()
if nvim_0_8 ~= nil then
return nvim_0_8
end
nvim_0_8 = vfn.has('nvim-0.8') == 1
if nvim_0_8 == false then
M.log('Please use navigator 0.4 version for neovim version < 0.8')
end
return nvim_0_8
end
function M.mk_handler(fn)
return function(...)
return fn(...)
end
end
function M.partial(func, arg)
return function(...)
return func(arg, ...)
end
end
function M.partial2(func, arg1, arg2)
return function(...)
return func(arg1, arg2, ...)
end
end
function M.partial3(func, arg1, arg2, arg3)
return function(...)
return func(arg1, arg2, arg3, ...)
end
end
function M.partial4(func, arg1, arg2, arg3, arg4)
return function(...)
return func(arg1, arg2, arg3, arg4, ...)
end
end
2 years ago
function M.empty(t)
if t == nil then
return true
end
if type(t) ~= 'table' then
return false
end
2 years ago
return next(t) == nil
end
function M.encoding(client)
if client == nil then
client = 1
end
if type(client) == 'number' then
client = vim.lsp.get_client_by_id(client) or {}
end
local oe = client.offset_encoding
if oe == nil then
return 'utf-8'
end
if type(oe) == 'table' then
return oe[1]
end
return oe
end
-- alternatively: use vim.notify("namespace does not exist or is anonymous", vim.log.levels.ERROR)
function M.warn(msg)
vim.notify('WRN: ' .. msg, vim.lsp.log_levels.WARN)
end
function M.error(msg)
vim.notify('ERR: ' .. msg, vim.lsp.log_levels.EROR)
end
function M.info(msg)
vim.notify('INF: ' .. msg, vim.lsp.log_levels.INFO)
end
function M.dedup(locations)
local m = 10
if m > #locations then
m = #locations
end
local dict = {}
local del = {}
for i = 1, m, 1 do
local value = locations[i]
local range = value.range or value.originSelectionRange or value.targetRange
if not range then
break
end
local key = (value.uri or range.uri or value.targetUri or '')
.. ':'
.. tostring(range.start.line)
.. ':'
.. tostring(range.start.character)
.. ':'
.. tostring(range['end'].line)
.. ':'
.. tostring(range['end'].character)
if dict[key] == nil then
dict[key] = i
else
local j = dict[key]
if not locations[j].definition then
table.insert(del, i)
else
table.insert(del, j)
end
end
end
table.sort(del)
for i = #del, 1, -1 do
M.log('remove ', del[i])
table.remove(locations, del[i])
end
return locations
end
function M.range_inside(outer, inner)
if outer == nil or inner == nil then
return false
end
if outer.start == nil or outer['end'] == nil or inner.start == nil or inner['end'] == nil then
return false
end
return outer.start.line <= inner.start.line and outer['end'].line >= inner['end'].line
end
function M.dirname(pathname)
local path_sep = require('navigator.util').path_sep()
local strip_dir_pat = path_sep .. '([^' .. path_sep .. ']+)$'
local strip_sep_pat = path_sep .. '$'
if not pathname or #pathname == 0 then
return
end
local result = pathname:gsub(strip_sep_pat, ''):gsub(strip_dir_pat, '')
if #result == 0 then
return '/'
end
return result
end
3 years ago
return M