Update treesitter adding arrow function and function types for

treesitter
neovim_0_5
ray-x 3 years ago
parent dc309fdad2
commit 7351a65917

@ -0,0 +1,3 @@
- Defination vs Reference (A seperate def call)
- Called by (which function calls this or reference the variable)
- inline edit in float window (Almost done)

@ -9,13 +9,10 @@ _NgConfigValues = {
-- -- your on_attach will be called at end of navigator on_attach
-- end,
sumneko_root_path = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server",
sumneko_binary = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server/bin/macOS/lua-language-server",
code_action_prompt = {
enable = true,
sign = true,
sign_priority = 40,
virtual_text = true
}
sumneko_binary = vim.fn.expand("$HOME") ..
"/github/sumneko/lua-language-server/bin/macOS/lua-language-server",
treesitter_call_tree = true,
code_action_prompt = {enable = true, sign = true, sign_priority = 40, virtual_text = true}
}
vim.cmd("command! -nargs=0 LspLog call v:lua.open_lsp_log()")
@ -23,27 +20,21 @@ vim.cmd("command! -nargs=0 LspRestart call v:lua.reload_lsp()")
local extend_config = function(opts)
opts = opts or {}
if next(opts) == nil then
return
end
if next(opts) == nil then return end
for key, value in pairs(opts) do
if _NgConfigValues[key] == nil then
error(string.format("[] Key %s not valid", key))
return
end
if type(M.config_values[key]) == "table" then
for k, v in pairs(value) do
_NgConfigValues[key][k] = v
end
for k, v in pairs(value) do _NgConfigValues[key][k] = v end
else
_NgConfigValues[key] = value
end
end
end
M.config_values = function()
return _NgConfigValues
end
M.config_values = function() return _NgConfigValues end
M.setup = function(cfg)
extend_config(cfg)

@ -5,8 +5,16 @@ local gui = require "navigator.gui"
local log = util.log
local TextView = require("guihua.textview")
-- callback for lsp definition, implementation and declaration handler
local function definition_hdlr(_, _, locations, _, bufnr)
local function definition_hdlr(err, _, locations, _, bufnr)
-- log(locations)
if err ~= nil then
print(err)
return
end
if type(locations) == "number" then
log(locations)
err("unable to handle request")
end
if locations == nil or vim.tbl_isempty(locations) then
print "Definition not found"
return
@ -38,9 +46,7 @@ local function def_preview(timeout_ms)
-- result = {vim.tbl_deep_extend("force", {}, unpack(result))}
-- log("def-preview", result)
for key, value in pairs(result) do
if result[key] ~= nil then
table.insert(data, value.result[1])
end
if result[key] ~= nil then table.insert(data, value.result[1]) end
end
local range = data[1].targetRange or data[1].range
@ -49,13 +55,9 @@ local function def_preview(timeout_ms)
row = math.max(row - 3, 1)
local delta = range.start.line - row + 1
local uri = data[1].uri or data[1].targetUri
if not uri then
return
end
if not uri then return end
local bufnr = vim.uri_to_bufnr(uri)
if not vim.api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
if not vim.api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end
-- TODO: 12 should be an option
local definition = vim.api.nvim_buf_get_lines(bufnr, row, range["end"].line + 12, false)
local def_line = vim.api.nvim_buf_get_lines(bufnr, range.start.line, range.start.line + 1, false)

@ -2,72 +2,78 @@ local M = {}
local ListView = require "guihua.listview"
local TextView = require "guihua.textview"
local util = require "navigator.util"
local log = require "navigator.util".log
local verbose = require "navigator.util".verbose
local log = require"navigator.util".log
local verbose = require"navigator.util".verbose
local api = vim.api
function M.new_preview(opts)
return TextView:new(
{
loc = "top_center",
rect = {
height = opts.preview_heigh or 12,
width = opts.width or 100,
pos_x = opts.pos_x or 0,
pos_y = opts.pos_y or 4
},
-- data = display_data,
relative = opts.relative,
data = opts.items,
syntax = opts.syntax,
enter = opts.enter or false,
hl_line = opts.hl_line
}
)
return TextView:new({
loc = "top_center",
rect = {
height = opts.height, -- opts.preview_heigh or 12, -- TODO 12
width = opts.width or 100,
pos_x = opts.pos_x or 0,
pos_y = opts.pos_y or 4
},
-- data = display_data,
relative = opts.relative,
-- data = opts.items, -- either items or uri
uri = opts.uri,
syntax = opts.syntax,
enter = opts.enter or false,
range = opts.range,
display_range = opts.display_range,
hl_line = opts.hl_line
})
end
function M._preview_location(opts) --location, width, pos_x, pos_y
local uri = opts.location.targetUri or opts.location.uri
function M._preview_location(opts) -- location, width, pos_x, pos_y
local uri = opts.location.uri
if opts.uri == nil then
log("invalid/nil uri ")
return
end
local bufnr = vim.uri_to_bufnr(uri)
if not api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
if not api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end
--
local range = opts.location.targetRange or opts.location.range
if range.start == nil then
print("error invalid range")
return
end
if range.start.line == nil then
range.start.line = range["end"].line - 1
opts.lnum = range["end"].line + 1
log(opts)
end
if range["end"].line == nil then
range["end"].line = range.start.line + 1
opts.lnum = range.start.line + 1
log(opts)
end
local contents = api.nvim_buf_get_lines(bufnr, range.start.line, (range["end"].line or 1) + 10, false)
local display_range = opts.location.range
-- if range.start == nil then
-- print("error invalid range")
-- return
-- end
-- if range.start.line == nil then
-- range.start.line = range["end"].line - 1
-- opts.lnum = range["end"].line + 1
-- log(opts)
-- end
-- if range["end"].line == nil then
-- range["end"].line = range.start.line + 1
-- opts.lnum = range.start.line + 1
-- log(opts)
-- end
-- TODO: preview height
-- local contents = api.nvim_buf_get_lines(bufnr, range.start.line, range["end"].line, false)
--
local syntax = api.nvim_buf_get_option(bufnr, "syntax")
if syntax == nil or #syntax < 1 then
syntax = api.nvim_buf_get_option(bufnr, "ft")
end
local syntax = api.nvim_buf_get_option(bufnr, "ft")
if syntax == nil or #syntax < 1 then syntax = "c" end
verbose(syntax, contents)
local win_opts = {syntax = syntax, width = opts.width, pos_x = opts.offset_x or 0, pos_y = opts.offset_y or 10}
win_opts.items = contents
win_opts.hl_line = opts.lnum - range.start.line
if win_opts.hl_line < 0 then
win_opts.hl_line = 1
end
verbose(opts.lnum, range.start.line, win_opts.hl_line)
-- verbose(syntax, contents)
local win_opts = {
syntax = syntax,
width = opts.width,
height = display_range['end'].line - display_range.start.line + 1,
pos_x = opts.offset_x or 0,
pos_y = opts.offset_y or 10,
range = opts.range,
display_range = display_range,
uri = uri,
allow_edit = true
}
-- win_opts.items = contents
win_opts.hl_line = opts.lnum - display_range.start.line
if win_opts.hl_line < 0 then win_opts.hl_line = 1 end
verbose(opts.lnum, opts.range.start.line, win_opts.hl_line)
local w = M.new_preview(win_opts)
return w
@ -75,15 +81,14 @@ end
function M.preview_uri(opts) -- uri, width, line, col, offset_x, offset_y
local line_beg = opts.lnum - 1
if line_beg >= 2 then
line_beg = line_beg - 2
end
local loc = {uri = opts.uri, targetRange = {start = {line = line_beg}}}
-- TODO: options for 8
loc.targetRange["end"] = {line = opts.lnum + 8}
if line_beg >= 2 then line_beg = line_beg - 2 end
local loc = {uri = opts.uri, range = {start = {line = line_beg}}}
-- TODO: preview height
loc.range["end"] = {line = opts.lnum + 12}
opts.location = loc
-- log("uri", opts.uri, opts.lnum, opts.location)
log("uri", opts.uri, opts.lnum, opts.location)
return M._preview_location(opts)
end
@ -92,69 +97,129 @@ function M.new_list_view(opts)
local items = opts.items
local data = {}
if opts.rawdata then
data = items
else
data = require "guihua.util".aggregate_filename(items, opts)
end
local wwidth = api.nvim_get_option("columns")
local width = math.min(opts.width or config.width or 120, math.floor(wwidth * 0.8))
local wheight = config.height or math.floor(api.nvim_get_option("lines") * 0.8)
local prompt = opts.prompt or false
opts.width = width
if opts.rawdata then
data = items
else
data = require"guihua.util".prepare_for_render(items, opts)
end
if data and not vim.tbl_isempty(data) then
-- replace
-- TODO: 10 vimrc opt
if #data > 10 and opts.prompt == nil then
prompt = true
end
if #data > 10 and opts.prompt == nil then prompt = true end
local height = math.min(#data, math.floor(wheight / 2))
local offset_y = height
if prompt then
offset_y = offset_y + 1
end
return ListView:new(
{
loc = "top_center",
prompt = prompt,
relative = opts.relative,
style = opts.style,
api = opts.api,
rect = {
height = height,
local offset_y = height + 2 -- style shadow took 2 lines
if prompt then offset_y = offset_y + 1 end
return ListView:new({
loc = "top_center",
prompt = prompt,
relative = opts.relative,
style = opts.style,
api = opts.api,
rect = {height = height, width = width, pos_x = 0, pos_y = 0},
ft = opts.ft or 'guihua',
-- data = display_data,
data = data,
on_confirm = opts.on_confirm or function(pos)
if pos == 0 then pos = 1 end
local l = data[pos]
if l.filename ~= nil then
verbose("openfile ", l.filename, l.lnum, l.col)
util.open_file_at(l.filename, l.lnum, l.col)
end
end,
on_move = opts.on_move or function(pos)
if pos == 0 then pos = 1 end
local l = data[pos]
verbose("on move", pos, l)
verbose("on move", pos, l.text or l, l.uri, l.filename)
-- todo fix
if l.uri == nil then l.uri = "file:///" .. l.filename end
return M.preview_uri({
uri = l.uri,
width = width,
pos_x = 0,
pos_y = 0
},
-- data = display_data,
data = data,
on_confirm = opts.on_confirm or function(pos)
if pos == 0 then
pos = 1
end
local l = data[pos]
if l.filename ~= nil then
verbose("openfile ", l.filename, l.lnum, l.col)
util.open_file_at(l.filename, l.lnum, l.col)
end
end,
on_move = opts.on_move or function(pos)
if pos == 0 then
pos = 1
end
local l = data[pos]
verbose("on move", pos, l.text or l, l.uri, l.filename)
-- todo fix
if l.uri == nil then
l.uri = "file:///" .. l.filename
end
return M.preview_uri(
{uri = l.uri, width = width, lnum = l.lnum, col = l.col, offset_x = 0, offset_y = offset_y}
)
end
}
)
lnum = l.lnum,
col = l.col,
range = l.range,
offset_x = 0,
offset_y = offset_y,
border = "double"
})
end
})
end
end
return M
-- Doc
--[[
-- each item should look like this
-- update if API changes
{
call_by = { <table 1> },
col = 40,
display_filename = "./curry.js",
filename = "/Users/ray.xu/lsp_test/js/curry.js",
lnum = 4,
range = {
end = {
character = 46,
line = 3 -- note: C index
},
start = {
character = 39,
line = 3
}
},
rpath = "js/curry.js",
text = " (sum, element, index) => (sum += element * vector2[index]),",
uri = "file:///Users/ray.xu/lsp_test/js/curry.js"
}
--]]
-- on move item:
--[[
call_by = { {
kind = "",
node_scope = {
end = {
character = 1,
line = 7
},
start = {
character = 0,
line = 0
}
},
node_text = "curriedDot",
type = "var"
} },
col = 22,
display_filename = "./curry.js",
filename = "/Users/ray.xu/lsp_test/js/curry.js",
lnum = 4,
range = {
end = {
character = 26,
line = 3
},
start = {
character = 21,
line = 3
}
},
rpath = "js/curry.js",
text = " 4: (sum, element, index) => (sum += element * vector   curriedDot()",
uri = "file:///Users/ray.xu/lsp_test/js/curry.js"
--
]]

@ -1,15 +1,17 @@
local gui = require "navigator.gui"
local util = require "navigator.util"
local log = util.log
local partial = util.partial
local partial = util.partial
local lsphelper = require "navigator.lspwrapper"
local cwd = vim.fn.getcwd(0)
local M = {}
local function call_hierarchy_handler(direction, err, _, result, _, _, error_message)
local function call_hierarchy_handler(direction, err, _, result, _, _,
error_message)
-- log('call_hierarchy')
assert(#vim.lsp.buf_get_clients() > 0, "Must have a client running to use lsp_tags")
assert(#vim.lsp.buf_get_clients() > 0,
"Must have a client running to use lsp_tags")
if err ~= nil then
print("ERROR: " .. error_message)
return
@ -21,24 +23,22 @@ local function call_hierarchy_handler(direction, err, _, result, _, _, error_mes
local call_hierarchy_item = call_hierarchy_call[direction]
local kind = ''
if call_hierarchy_item.kind then
kind = require'navigator.lspclient.lspkind'.symbol_kind(call_hierarchy_item.kind) .. ' '
kind = require'navigator.lspclient.lspkind'.symbol_kind(
call_hierarchy_item.kind) .. ' '
end
for _, range in pairs(call_hierarchy_call.fromRanges) do
local filename = assert(vim.uri_to_fname(call_hierarchy_item.uri))
local display_filename = filename:gsub(cwd .. "/", "./", 1)
table.insert(
items,
{
uri = call_hierarchy_item.uri,
filename = filename,
-- display_filename = filename:gsub(cwd .. "/", "./", 1),
display_filename = call_hierarchy_item.detail or display_filename,
text = kind .. call_hierarchy_item.name,
range = range,
lnum = range.start.line,
col = range.start.character
}
)
table.insert(items, {
uri = call_hierarchy_item.uri,
filename = filename,
-- display_filename = filename:gsub(cwd .. "/", "./", 1),
display_filename = call_hierarchy_item.detail or display_filename,
text = kind .. call_hierarchy_item.name,
range = range,
lnum = range.start.line,
col = range.start.character
})
end
end
return items
@ -47,38 +47,45 @@ end
local call_hierarchy_handler_from = partial(call_hierarchy_handler, "from")
local call_hierarchy_handler_to = partial(call_hierarchy_handler, "to")
local function incoming_calls_handler(bang, err, method, result, client_id, bufnr)
assert(#vim.lsp.buf_get_clients() > 0, "Must have a client running to use lsp_tags")
local results = call_hierarchy_handler_from(err, method, result, client_id, bufnr, "Incoming calls not found")
gui.new_list_view({items = results, api = ''})
local function incoming_calls_handler(bang, err, method, result, client_id,
bufnr)
assert(#vim.lsp.buf_get_clients() > 0,
"Must have a client running to use lsp_tags")
local results = call_hierarchy_handler_from(err, method, result, client_id,
bufnr, "Incoming calls not found")
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
gui.new_list_view({items = results, ft = ft, api = ''})
end
local function outgoing_calls_handler(bang, err, method, result, client_id, bufnr)
local results = call_hierarchy_handler_to(err, method, result, client_id, bufnr, "Outgoing calls not found")
local function outgoing_calls_handler(bang, err, method, result, client_id,
bufnr)
local results = call_hierarchy_handler_to(err, method, result, client_id,
bufnr, "Outgoing calls not found")
gui.new_list_view({items =results, api = ''})
--fzf_locations(bang, "", "Outgoing Calls", results, false)
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
gui.new_list_view({items = results, ft = ft, api = ''})
-- fzf_locations(bang, "", "Outgoing Calls", results, false)
end
function M.incoming_calls(bang, opts)
assert(#vim.lsp.buf_get_clients() > 0, "Must have a client running to use lsp_tags")
if not lsphelper.check_capabilities("call_hierarchy") then
return
end
assert(#vim.lsp.buf_get_clients() > 0,
"Must have a client running to use lsp_tags")
if not lsphelper.check_capabilities("call_hierarchy") then return end
local params = vim.lsp.util.make_position_params()
util.call_sync("callHierarchy/incomingCalls", params, opts, partial(incoming_calls_handler, bang))
util.call_sync("callHierarchy/incomingCalls", params, opts,
partial(incoming_calls_handler, bang))
end
function M.outgoing_calls(bang, opts)
assert(#vim.lsp.buf_get_clients() > 0, "Must have a client running to use lsp_tags")
if not lsphelper.check_capabilities("call_hierarchy") then
return
end
assert(#vim.lsp.buf_get_clients() > 0,
"Must have a client running to use lsp_tags")
if not lsphelper.check_capabilities("call_hierarchy") then return end
local params = vim.lsp.util.make_position_params()
util.call_sync("callHierarchy/outgoingCalls", params, opts, partial(outgoing_calls_handler, bang))
util.call_sync("callHierarchy/outgoingCalls", params, opts,
partial(outgoing_calls_handler, bang))
end
M.incoming_calls_call = partial(M.incoming_calls, 0)

@ -17,20 +17,18 @@ end
local function implementation_handler(bang, err, method, result, client_id, bufnr)
local results = location_handler(err, method, result, client_id, bufnr, "Implementation not found")
gui.new_list_view({items =results, api = 'Implementation'})
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
gui.new_list_view({items = results, ft = ft, api = 'Implementation'})
end
function M.implementation(bang, opts)
if not lsphelper.check_capabilities("implementation") then
return
end
if not lsphelper.check_capabilities("implementation") then return end
local params = vim.lsp.util.make_position_params()
util.call_sync("textDocument/implementation", params, opts, partial(implementation_handler, bang))
end
M.implementation_call = partial(M.implementation, 0)
M.implementation_handler = partial(implementation_handler, 0)

@ -3,6 +3,7 @@ local lsp = require("vim.lsp")
local util = require "navigator.util"
local log = util.log
local verbose = util.verbose
local diagnostic_map = function(bufnr)
local opts = {noremap = true, silent = true}
@ -11,37 +12,41 @@ end
local M = {}
M.on_attach = function(client, bufnr)
log("attaching")
local uri = vim.uri_from_bufnr(bufnr)
local hassig, sig = pcall(require, "lsp_signature")
if hassig then
sig.on_attach()
log("loading for ft ", ft, uri)
if uri == 'file://' or uri == 'file:///' then
log("skip loading for ft ", ft, uri)
return
end
log("attaching", bufnr)
verbose(client)
local hassig, sig = pcall(require, "lsp_signature")
if hassig then sig.on_attach() end
diagnostic_map(bufnr)
-- lspsaga
require "navigator.lspclient.highlight".add_highlight()
require"navigator.lspclient.highlight".add_highlight()
api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")
require("navigator.lspclient.mapping").setup({client = client, bufnr = bufnr, cap = client.resolved_capabilities})
require("navigator.lspclient.mapping").setup({
client = client,
bufnr = bufnr,
cap = client.resolved_capabilities
})
if client.resolved_capabilities.document_highlight then
require("navigator.dochighlight").documentHighlight()
end
require "navigator.lspclient.lspkind".init()
require"navigator.lspclient.lspkind".init()
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true
local config = require "navigator".config_value
if config ~= nil and config.on_attach ~= nil then
config.on_attach(client, bufnr)
end
local config = require"navigator".config_value
if config ~= nil and config.on_attach ~= nil then config.on_attach(client, bufnr) end
end
M.setup = function(cfg)
return M
end
M.setup = function(cfg) return M end
return M

@ -1,29 +1,26 @@
-- todo allow config passed in
local log = require "navigator.util".log
local verbose = require "navigator.util".verbose
local log = require"navigator.util".log
local verbose = require"navigator.util".verbose
_Loading = false
if packer_plugins ~= nil then
-- packer installed
local loader = require "packer".loader
if not packer_plugins["neovim/nvim-lspconfig"] or not packer_plugins["neovim/nvim-lspconfig"].loaded then
loader("nvim-lspconfig")
end
local loader = require"packer".loader
if not packer_plugins["neovim/nvim-lspconfig"] or
not packer_plugins["neovim/nvim-lspconfig"].loaded then loader("nvim-lspconfig") end
if not packer_plugins["ray-x/guihua.lua"] or not packer_plugins["guihua.lua"].loaded then
loader("guihua.lua")
-- if lazyloading
-- if lazyloading
end
end
local has_lsp, lspconfig = pcall(require, "lspconfig")
if not has_lsp then
error("loading lsp config")
end
if not has_lsp then error("loading lsp config") end
local highlight = require "navigator.lspclient.highlight"
local util = lspconfig.util
local config = require "navigator".config_values()
local config = require"navigator".config_values()
local cap = vim.lsp.protocol.make_client_capabilities()
local on_attach = require("navigator.lspclient.attach").on_attach
@ -32,6 +29,37 @@ local on_attach = require("navigator.lspclient.attach").on_attach
-- lua setup
local sumneko_root_path = config.sumneko_root_path
local sumneko_binary = config.sumneko_binary
local library = {}
local path = vim.split(package.path, ";")
table.insert(path, "lua/?.lua")
table.insert(path, "lua/?/init.lua")
local function add(lib)
for _, p in pairs(vim.fn.expand(lib, false, true)) do
p = vim.loop.fs_realpath(p)
library[p] = true
end
end
-- add runtime
add("$VIMRUNTIME")
-- add your config
local home = vim.fn.expand("$HOME")
if vim.fn.isdirectory(home .. "/.config/nvim") then add(home .. "/.config/nvim") end
-- add plugins it may be very slow to add all in path
-- if vim.fn.isdirectory(home .. "/.config/share/nvim/site/pack/packer") then
-- add(home .. "/.local/share/nvim/site/pack/packer/opt/*")
-- add(home .. "/.local/share/nvim/site/pack/packer/start/*")
-- end
library[vim.fn.expand("$VIMRUNTIME/lua")] = true
library[vim.fn.expand("$VIMRUNTIME/lua/vim")] = true
library[vim.fn.expand("$VIMRUNTIME/lua/vim/lsp")] = true
-- [vim.fn.expand("~/repos/nvim/lua")] = true
local setups = {
gopls = {
@ -40,11 +68,8 @@ local setups = {
filetypes = {"go", "gomod"},
message_level = vim.lsp.protocol.MessageType.Error,
cmd = {
"gopls",
-- share the gopls instance if there is one already
"-remote=auto",
--[[ debug options ]]
--
"gopls", -- share the gopls instance if there is one already
"-remote=auto", --[[ debug options ]] --
-- "-logfile=auto",
-- "-debug=:0",
"-remote.debug=:0"
@ -73,10 +98,7 @@ local setups = {
},
clangd = {
cmd = {
"clangd",
"--background-index",
"--suggest-missing-includes",
"--clang-tidy",
"clangd", "--background-index", "--suggest-missing-includes", "--clang-tidy",
"--header-insertion=iwyu"
},
filetypes = {"c", "cpp", "objc", "objcpp"},
@ -87,7 +109,8 @@ local setups = {
},
rust_analyzer = {
root_dir = function(fname)
return util.root_pattern("Cargo.toml", "rust-project.json", ".git")(fname) or util.path.dirname(fname)
return util.root_pattern("Cargo.toml", "rust-project.json", ".git")(fname) or
util.path.dirname(fname)
end,
filetypes = {"rust"},
message_level = vim.lsp.protocol.MessageType.error,
@ -105,7 +128,7 @@ local setups = {
on_attach = function(client, bufnr)
client.resolved_capabilities.execute_command = true
highlight.diagnositc_config_sign()
require "sqls".setup {picker = "telescope"} -- or default
require"sqls".setup {picker = "telescope"} -- or default
end,
settings = {
cmd = {"sqls", "-config", "$HOME/.config/sqls/config.yml"}
@ -133,25 +156,16 @@ local setups = {
diagnostics = {
enable = true,
-- Get the language server to recognize the `vim` global
globals = {
"vim",
"describe",
"it",
"before_each",
"after_each",
"teardown",
"pending"
}
globals = {"vim", "describe", "it", "before_each", "after_each", "teardown", "pending"}
},
completion = {callSnippet = "Both"},
workspace = {
-- Make the server aware of Neovim runtime files
library = {
[vim.fn.expand("$VIMRUNTIME/lua")] = true,
[vim.fn.expand("$VIMRUNTIME/lua/vim")] = true,
[vim.fn.expand("$VIMRUNTIME/lua/vim/lsp")] = true
-- [vim.fn.expand("~/repos/nvim/lua")] = true
}
}
library = library,
maxPreload = 256,
preloadFileSize = 50000
},
telemetry = {enable = false}
}
}
},
@ -172,49 +186,17 @@ local setups = {
init_options = {
compilationDatabaseDirectory = "build",
root_dir = [[ util.root_pattern("compile_commands.json", "compile_flags.txt", "CMakeLists.txt", "Makefile", ".git") or util.path.dirname ]],
index = {
threads = 2
},
clang = {
excludeArgs = {"-frounding-math"}
}
index = {threads = 2},
clang = {excludeArgs = {"-frounding-math"}}
}
}
}
local servers = {
"angularls",
"gopls",
"tsserver",
"flow",
"bashls",
"dockerls",
"julials",
"pyls",
"pyright",
"jedi_language_server",
"jdtls",
"sumneko_lua",
"vimls",
"html",
"jsonls",
"solargraph",
"cssls",
"yamlls",
"clangd",
"ccls",
"sqls",
"denols",
"dartls",
"dotls",
"kotlin_language_server",
"nimls",
"intelephense",
"vuels",
"phpactor",
"omnisharp",
"r_language_server",
"rust_analyzer",
"angularls", "gopls", "tsserver", "flow", "bashls", "dockerls", "julials", "pyls", "pyright",
"jedi_language_server", "jdtls", "sumneko_lua", "vimls", "html", "jsonls", "solargraph", "cssls",
"yamlls", "clangd", "ccls", "sqls", "denols", "dartls", "dotls", "kotlin_language_server",
"nimls", "intelephense", "vuels", "phpactor", "omnisharp", "r_language_server", "rust_analyzer",
"terraformls"
}
@ -232,16 +214,12 @@ local function load_cfg(ft, client, cfg, loaded)
local should_load = false
if lspft ~= nil and #lspft > 0 then
for _, value in ipairs(lspft) do
if ft == value then
should_load = true
end
end
for _, value in ipairs(lspft) do if ft == value then should_load = true end end
if should_load then
for _, c in pairs(loaded) do
if client == c then
-- loaded
log(client, "already been loaded for", ft, loaded)
verbose(client, "already been loaded for", ft, loaded)
return
end
end
@ -258,35 +236,27 @@ local function wait_lsp_startup(ft, retry)
local loaded = {}
for i = 1, 2 do
for _, client in ipairs(clients) do
if client ~= nil then
table.insert(loaded, client.name)
end
if client ~= nil then table.insert(loaded, client.name) end
end
for _, lspclient in ipairs(servers) do
local cfg = setups[lspclient] or default_cfg
load_cfg(ft, lspclient, cfg, loaded)
end
if not retry or ft == nil then
return
end
if not retry or ft == nil then return end
--
local timer = vim.loop.new_timer()
local i = 0
vim.wait(
1000,
function()
clients = vim.lsp.get_active_clients() or {}
i = i + 1
if i > 5 or #clients > 0 then
timer:close() -- Always close handles to avoid leaks.
log("active", #clients, i)
_Loading = false
return true
end
vim.wait(1000, function()
clients = vim.lsp.get_active_clients() or {}
i = i + 1
if i > 5 or #clients > 0 then
timer:close() -- Always close handles to avoid leaks.
verbose("active", #clients, i)
_Loading = false
end,
200
)
return true
end
_Loading = false
end, 200)
end
end
@ -294,39 +264,36 @@ vim.cmd([[autocmd FileType * lua require'navigator.lspclient.clients'.setup()]])
local function setup(user_opts)
verbose(debug.traceback())
if _Loading == true then
if lspconfig == nil then
error("lsp-config need installed and enabled")
return
end
if _Loading == true then return end
local ft = vim.bo.filetype
if ft == nil then
ft = vim.api.nvim_buf_get_option(0, "filetype")
end
if ft == nil then ft = vim.api.nvim_buf_get_option(0, "filetype") end
if ft == nil or ft == "" then
log("nil filetype")
return
end
log("loading for ft ", ft)
local retry = true
local disable_ft = {
"NvimTree",
"guihua",
"clap_input",
"clap_spinner",
"vista",
"TelescopePrompt",
"csv",
"txt",
"markdown",
"defx"
"NvimTree", "guihua", "clap_input", "clap_spinner", "vista", "vista_kind", "TelescopePrompt",
"csv", "txt", "markdown", "defx"
}
for i = 1, #disable_ft do
if ft == disable_ft[i] then
log("navigator disabled for ft", ft)
return
end
end
if lspconfig == nil then
error("lsp-config need installed and enabled")
local bufnr = vim.fn.bufnr()
local uri = vim.uri_from_bufnr(bufnr)
log("loading for ft ", ft, uri)
if uri == 'file://' or uri == 'file:///' then
log("skip loading for ft ", ft, uri)
return
end

@ -23,37 +23,13 @@ local kind_symbols = {
Struct = "",
Event = "",
Operator = "",
TypeParameter = "",
TypeParameter = "",
Default = ""
}
local CompletionItemKind = {
"",
"𝔉 ",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"𝕰 ",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
"", "𝔉 ", "", "", "", "", "", "", "", "", "", "", "𝕰 ", "",
"", "", "", "", "", "", "", "", "", "", "", ""
}
-- A symbol kind.
@ -87,18 +63,14 @@ local SymbolKind = {
}
local SymbolItemKind = {
"", "", "", "", "", "ƒ ", "", "", "", "𝕰 ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }
"", "", "", "", "", "ƒ ", "", "", "", "𝕰 ", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", ""
}
local lspkind = {}
function lspkind.comp_kind(kind)
return CompletionItemKind[kind] or ""
end
function lspkind.comp_kind(kind) return CompletionItemKind[kind] or "" end
function lspkind.symbol_kind(kind)
return SymbolItemKind[kind] or ""
end
function lspkind.symbol_kind(kind) return SymbolItemKind[kind] or "" end
function lspkind.init()
require('vim.lsp.protocol').CompletionItemKind = CompletionItemKind
end
function lspkind.init() require('vim.lsp.protocol').CompletionItemKind = CompletionItemKind end
return lspkind

@ -3,7 +3,8 @@ local function set_keymap(...) vim.api.nvim_set_keymap(...) end
local event_hdlrs = {
{ev = "BufWritePre", func = "diagnostic.set_loclist({open_loclist = false})"},
{ev = "CursorHold", func = "document_highlight()"}, {ev = "CursorHoldI", func = "document_highlight()"},
{ev = "CursorHold", func = "document_highlight()"},
{ev = "CursorHoldI", func = "document_highlight()"},
{ev = "CursorMoved", func = "clear_references()"}
}
@ -11,13 +12,15 @@ local key_maps = {
{key = "gr", func = "references()"}, {mode = "i", key = "<M-k>", func = "signature_help()"},
{key = "gs", func = "signature_help()"}, {key = "g0", func = "document_symbol()"},
{key = "gW", func = "workspace_symbol()"}, {key = "<c-]>", func = "definition()"},
{key = "gD", func = "declaration()"}, {key = "gp", func = "require('navigator.definition').definition_preview()"},
{key = "gD", func = "declaration()"},
{key = "gp", func = "require('navigator.definition').definition_preview()"},
{key = "gT", func = "require('navigator.treesitter').buf_ts()"},
{key = "GT", func = "require('navigator.treesitter').bufs_ts()"}, {key = "K", func = "hover()"},
{key = "ga", mode = "n", func = "code_action()"}, {key = "ga", mode = "v", func = "range_code_action()"},
{key = "<Leader>re", func = "rename()"}, {key = "<Leader>gi", func = "incoming_calls()"},
{key = "<Leader>go", func = "outgoing_calls()"}, {key = "gi", func = "implementation()"},
{key = "gt", func = "type_definition()"}, {key = "gL", func = "diagnostic.show_line_diagnostics()"},
{key = "ga", mode = "n", func = "code_action()"},
{key = "ga", mode = "v", func = "range_code_action()"}, {key = "<Leader>re", func = "rename()"},
{key = "<Leader>gi", func = "incoming_calls()"}, {key = "<Leader>go", func = "outgoing_calls()"},
{key = "gi", func = "implementation()"}, {key = "gt", func = "type_definition()"},
{key = "gL", func = "diagnostic.show_line_diagnostics()"},
{key = "gG", func = "require('navigator.diagnostics').show_diagnostic()"},
{key = "]d", func = "diagnostic.goto_next()"}, {key = "[d", func = "diagnostic.goto_prev()"},
{key = "]r", func = "require('navigator.treesitter').goto_next_usage()"},
@ -77,7 +80,9 @@ local function set_mapping(user_opts)
vim.cmd([[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting()]])
end
-- if user_opts.cap.document_range_formatting then
if range_fmt then buf_set_keymap("v", "<space>ff", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts) end
if range_fmt then
buf_set_keymap("v", "<space>ff", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
end
end
local function set_event_handler(user_opts)
@ -94,7 +99,8 @@ local function set_event_handler(user_opts)
else
f = "lua vim.lsp.buf." .. value.func
end
local cmd = "autocmd FileType " .. file_types .. " autocmd nvim_lsp_autos " .. value.ev .. " <buffer> silent! " .. f
local cmd = "autocmd FileType " .. file_types .. " autocmd nvim_lsp_autos " .. value.ev ..
" <buffer> silent! " .. f
vim.api.nvim_command(cmd)
end
vim.api.nvim_command([[augroup END]])
@ -110,8 +116,10 @@ function M.setup(user_opts)
set_event_handler(user_opts)
local cap = user_opts.cap or {}
if cap.call_hierarchy or cap.callHierarchy then
vim.lsp.handlers["callHierarchy/incomingCalls"] = require"navigator.hierarchy".incoming_calls_handler
vim.lsp.handlers["callHierarchy/outgoingCalls"] = require"navigator.hierarchy".outgoing_calls_handler
vim.lsp.handlers["callHierarchy/incomingCalls"] =
require"navigator.hierarchy".incoming_calls_handler
vim.lsp.handlers["callHierarchy/outgoingCalls"] =
require"navigator.hierarchy".outgoing_calls_handler
end
vim.lsp.handlers["textDocument/references"] = require"navigator.reference".reference_handler
@ -122,15 +130,21 @@ function M.setup(user_opts)
vim.lsp.handlers["textDocument/declaration"] = require"navigator.definition".declaration_handler
end
vim.lsp.handlers["textDocument/typeDefinition"] = require"navigator.definition".typeDefinition_handler
vim.lsp.handlers["textDocument/implementation"] = require"navigator.implementation".implementation_handler
vim.lsp.handlers["textDocument/typeDefinition"] =
require"navigator.definition".typeDefinition_handler
vim.lsp.handlers["textDocument/implementation"] =
require"navigator.implementation".implementation_handler
vim.lsp.handlers["textDocument/documentSymbol"] = require"navigator.symbols".document_symbol_handler
vim.lsp.handlers["textDocument/documentSymbol"] =
require"navigator.symbols".document_symbol_handler
vim.lsp.handlers["workspace/symbol"] = require"navigator.symbols".workspace_symbol_handler
vim.lsp.handlers["textDocument/publishDiagnostics"] = require"navigator.diagnostics".diagnostic_handler
vim.lsp.handlers["textDocument/publishDiagnostics"] =
require"navigator.diagnostics".diagnostic_handler
local hassig, sig = pcall(require, "lsp_signature")
if not hassig then vim.lsp.handlers["textDocument/signatureHelp"] = require"navigator.signature".signature_handler end
if not hassig then
vim.lsp.handlers["textDocument/signatureHelp"] = require"navigator.signature".signature_handler
end
-- vim.lsp.handlers["textDocument/hover"] = require 'navigator.hover'.hover_handler
end

@ -2,10 +2,18 @@ local M = {}
local util = require "navigator.util"
local gutil = require "guihua.util"
local lsp = require "vim.lsp"
local log = require "navigator.util".log
local symbol_kind = require "navigator.lspclient.lspkind".symbol_kind
local api = vim.api
local log = require"navigator.util".log
local verbose = require"navigator.util".verbose
local symbol_kind = require"navigator.lspclient.lspkind".symbol_kind
local cwd = vim.fn.getcwd(0)
cwd = gutil.add_pec(cwd)
ts_nodes = {}
ts_nodes_time = {}
local ts_enabled, ts_locals = pcall(require, "nvim-treesitter.locals")
local calltree_enabled = require"navigator".config_values().treesitter_call_tree
function M.lines_from_locations(locations, include_filename)
local fnamemodify = (function(filename)
if include_filename then
@ -17,10 +25,8 @@ function M.lines_from_locations(locations, include_filename)
local lines = {}
for _, loc in ipairs(locations) do
table.insert(
lines,
(fnamemodify(loc["filename"]) .. loc["lnum"] .. ":" .. loc["col"] .. ": " .. vim.trim(loc["text"]))
)
table.insert(lines, (fnamemodify(loc["filename"]) .. loc["lnum"] .. ":" .. loc["col"] .. ": " ..
vim.trim(loc["text"])))
end
return lines
@ -35,11 +41,9 @@ function M.symbols_to_items(result)
item.kind = result[i].kind
local kind = symbol_kind(item.kind)
item.name = result[i].name --symbol name
item.name = result[i].name -- symbol name
item.text = result[i].name
if kind ~= nil then
item.text = kind .. ": " .. item.text
end
if kind ~= nil then item.text = kind .. ": " .. item.text end
item.filename = vim.uri_to_fname(item.uri)
item.display_filename = item.filename:gsub(cwd .. "/", "./", 1)
@ -48,9 +52,7 @@ function M.symbols_to_items(result)
end
item.lnum = item.range.start.line + 1
if item.containerName ~= nil then
item.text = "" .. item.containerName .. item.text
end
if item.containerName ~= nil then item.text = "" .. item.containerName .. item.text end
table.insert(locations, item)
end
end
@ -63,9 +65,7 @@ local function extract_result(results_lsp)
if results_lsp then
local results = {}
for _, server_results in pairs(results_lsp) do
if server_results.result then
vim.list_extend(results, server_results.result)
end
if server_results.result then vim.list_extend(results, server_results.result) end
end
return results
@ -78,9 +78,7 @@ function M.check_capabilities(feature, client_id)
local supported_client = false
for _, client in pairs(clients) do
supported_client = client.resolved_capabilities[feature]
if supported_client then
goto continue
end
if supported_client then goto continue end
end
::continue::
@ -99,7 +97,8 @@ end
function M.call_sync(method, params, opts, handler)
params = params or {}
opts = opts or {}
local results_lsp, err = lsp.buf_request_sync(0, method, params, opts.timeout or vim.g.navtator_timeout)
local results_lsp, err = lsp.buf_request_sync(0, method, params,
opts.timeout or vim.g.navtator_timeout or 1000)
handler(err, method, extract_result(results_lsp), nil, nil)
end
@ -110,44 +109,86 @@ function M.call_async(method, params, handler)
util.show(...)
handler(...)
end
return lsp.buf_request(0, method, params, callback)
return lsp.buf_request(0, method, params, callback)
-- results_lsp, canceller
end
local function ts_functions(uri)
if not ts_enabled or not calltree_enabled then return nil end
local ts_func = require"navigator.treesitter".buf_func
local bufnr = vim.uri_to_bufnr(uri)
local x = os.clock()
if ts_nodes[uri] ~= nil then
local t = ts_nodes_time[uri]
local fname = vim.uri_to_fname(uri)
local modified = vim.fn.getftime(fname)
if modified < t then return ts_nodes[uri] end
end
local unload = false
if not api.nvim_buf_is_loaded(bufnr) then
log("! load buf !", uri, bufnr)
vim.fn.bufload(bufnr)
unload = true
end
local funcs = ts_func(bufnr)
if unload then
local cmd = string.format("bd %d", bufnr)
log(cmd)
-- vim.cmd(cmd) -- todo: not sure if it is needed
end
ts_nodes[uri] = funcs
ts_nodes_time[uri] = os.time()
verbose(funcs)
log(string.format("elapsed time: %.4f\n", os.clock() - x))
return funcs
end
local function find_ts_func_by_range(funcs, range)
if funcs == nil or range == nil then return nil end
local result = {}
verbose(funcs, range)
for _, value in pairs(funcs) do
local func_range = value.node_scope
-- note treesitter is C style
if func_range and func_range.start.line + 1 <= range.start.line and func_range['end'].line + 1 >=
range['end'].line then table.insert(result, value) end
end
return result
end
function M.locations_to_items(locations)
if not locations or vim.tbl_isempty(locations) then
print("list not avalible")
return
end
local width = 4
local items = {} -- lsp.util.locations_to_items(locations)
-- items and locations may not matching
table.sort(
locations,
function(i, j)
if i.uri == j.uri then
if i.range and i.range.start then
return i.range.start.line < j.range.start.line
end
return false
else
return i.uri < j.uri
end
table.sort(locations, function(i, j)
if i.uri == j.uri then
if i.range and i.range.start then return i.range.start.line < j.range.start.line end
return false
else
return i.uri < j.uri
end
)
end)
for i, loc in ipairs(locations) do
local item = lsp.util.locations_to_items({loc})[1]
item.uri = locations[i].uri
local funcs = ts_functions(item.uri)
item.range = locations[i].range
item.filename = assert(vim.uri_to_fname(item.uri))
local filename = item.filename:gsub(cwd .. "/", "./", 1)
item.display_filename = filename or item.filename
item.call_by = find_ts_func_by_range(funcs, item.range)
item.rpath = util.get_relative_path(cwd, item.filename)
table.insert(items, item)
width = math.max(width, #item.text)
end
return items
return items, width + 15
end
function M.symbol_to_items(locations)
@ -158,20 +199,15 @@ function M.symbol_to_items(locations)
local items = {} -- lsp.util.locations_to_items(locations)
-- items and locations may not matching
table.sort(
locations,
function(i, j)
if i.uri == j.uri then
if i.range and i.range.start then
return i.range.start.line < j.range.start.line
end
return false
else
return i.uri < j.uri
end
table.sort(locations, function(i, j)
if i.uri == j.uri then
if i.range and i.range.start then return i.range.start.line < j.range.start.line end
return false
else
return i.uri < j.uri
end
)
for i, loc in ipairs(locations) do
end)
for i, _ in ipairs(locations) do
local item = {} -- lsp.util.locations_to_items({loc})[1]
item.uri = locations[i].uri
item.range = locations[i].range

@ -3,39 +3,51 @@ local log = util.log
local lsphelper = require "navigator.lspwrapper"
local gui = require "navigator.gui"
local lsp = require "navigator.lspwrapper"
local verbose = require "navigator.util".verbose
local verbose = require"navigator.util".verbose
-- local log = util.log
-- local partial = util.partial
-- local cwd = vim.fn.getcwd(0)
-- local lsphelper = require "navigator.lspwrapper"
local locations_to_items = lsphelper.locations_to_items
--vim.api.nvim_set_option("navtator_options", {width = 90, height = 60, location = require "navigator.location".center})
-- vim.api.nvim_set_option("navtator_options", {width = 90, height = 60, location = require "navigator.location".center})
-- local options = vim.g.navtator_options or {width = 60, height = 40, location = location.center}
local function ref_hdlr(arg1, api, locations, num, bufnr)
local function ref_hdlr(err, api, locations, num, bufnr)
local opts = {}
-- log("arg1", arg1)
-- log(api)
-- log(locations)
-- log("num", num)
-- log("bfnr", bufnr)
if err ~= nil then
print('ref callback error, lsp may not ready', err)
return
end
if type(locations) ~= 'table' then
log("arg1", arg1)
log(api)
log(locations)
log("num", num)
log("bfnr", bufnr)
error(locations)
end
if locations == nil or vim.tbl_isempty(locations) then
print "References not found"
return
end
verbose(locations)
local items = locations_to_items(locations)
gui.new_list_view({items = items, api = "Reference"})
local items, width = locations_to_items(locations)
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
local wwidth = vim.api.nvim_get_option("columns")
width = math.min(width + 24 or 120, math.floor(wwidth * 0.8))
gui.new_list_view({items = items, ft = ft, width = width, api = "Reference"})
end
local async_reference_request = function()
local method = {"textDocument/references"}
local ref_params = vim.lsp.util.make_position_params()
ref_params.context = {includeDeclaration = true}
return lsp.call_async(method[1], ref_params, ref_hdlr) -- return asyncresult, canceller
lsp.call_async("textDocument/references", ref_params, ref_hdlr) -- return asyncresult, canceller
-- lsp.call_async("textDocument/definition", ref_params, ref_hdlr) -- return asyncresult, canceller
end
return {
reference_handler = ref_hdlr,
show_reference = async_reference_request
}
return {reference_handler = ref_hdlr, show_reference = async_reference_request}

@ -1,10 +1,10 @@
local gui = require "navigator.gui"
local M = {}
local log = require "navigator.util".log
local log = require"navigator.util".log
local lsphelper = require "navigator.lspwrapper"
local locations_to_items = lsphelper.locations_to_items
local clone = require "guihua.util".clone
local symbol_kind = require "navigator.lspclient.lspkind".symbol_kind
local clone = require"guihua.util".clone
local symbol_kind = require"navigator.lspclient.lspkind".symbol_kind
local symbols_to_items = lsphelper.symbols_to_items
-- function M.document_symbols(opts)
@ -46,7 +46,8 @@ function M.workspace_symbols(opts)
local params = vim.lsp.util.make_position_params()
params.context = {includeDeclaration = true}
params.query = opts.prompt or ""
local results_lsp = vim.lsp.buf_request_sync(0, "workspace/symbol", params, lspopts.timeout or 15000)
local results_lsp = vim.lsp.buf_request_sync(0, "workspace/symbol", params,
lspopts.timeout or 15000)
if not results_lsp or vim.tbl_isempty(results_lsp) then
print(bufnr, "symbol not found for buf")
return
@ -54,16 +55,18 @@ function M.workspace_symbols(opts)
-- result_lsp
local result = {}
for i = 1, #results_lsp do
if results_lsp[i] ~= nil and results_lsp[i].result ~= nil and #results_lsp[i].result > 0 then
result = results_lsp[i].result
end
if results_lsp[i] ~= nil and results_lsp[i].result ~= nil and
#results_lsp[i].result > 0 then result = results_lsp[i].result end
end
local items = symbols_to_items(result)
-- log(#items, items[1])
local ft = vim.api.nvim_buf_get_option(0, "ft")
if #items > 0 then
lspopts.items = items
lspopts.ft = ft
gui.new_list_view(lspopts)
else
print("symbols not found")
@ -71,9 +74,7 @@ function M.workspace_symbols(opts)
end
function M.document_symbol_handler(err, _, result, _, bufnr)
if err then
print(bufnr, "failed to get document symbol")
end
if err then print(bufnr, "failed to get document symbol") end
if not result or vim.tbl_isempty(result) then
print(bufnr, "symbol not found for buf")
@ -94,9 +95,7 @@ function M.document_symbol_handler(err, _, result, _, bufnr)
item.uri = uri
item.selectionRange = result[i].selectionRange
item.detail = result[i].detail or ""
if item.detail == "()" then
item.detail = "func"
end
if item.detail == "()" then item.detail = "func" end
item.lnum = result[i].range.start.line + 1
item.text = "[" .. kind .. "]" .. item.detail .. " " .. item.name
@ -116,14 +115,23 @@ function M.document_symbol_handler(err, _, result, _, bufnr)
child.uri = uri
child.lnum = c.range.start.line + 1
child.detail = c.detail or ""
child.text = "  [" .. ckind .. "] " .. child.detail .. " " .. child.name
child.text = "  [" .. ckind .. "] " .. child.detail .. " " ..
child.name
table.insert(locations, child)
end
end
end
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
-- verbose(locations)
-- local items = locations_to_items(locations)
gui.new_list_view({items = locations, prompt = true, rawdata = true, api = ""})
gui.new_list_view({
items = locations,
prompt = true,
rawdata = true,
ft = ft,
api = ""
})
-- if locations == nil or vim.tbl_isempty(locations) then
-- print "References not found"
@ -147,9 +155,7 @@ function M.document_symbol_handler(err, _, result, _, bufnr)
end
function M.workspace_symbol_handler(err, _, result, _, bufnr)
if err then
print(bufnr, "failed to get workspace symbol")
end
if err then print(bufnr, "failed to get workspace symbol") end
if not result or vim.tbl_isempty(result) then
print(bufnr, "symbol not found for buf")
return
@ -170,7 +176,15 @@ function M.workspace_symbol_handler(err, _, result, _, bufnr)
-- table.insert(locations, item)
-- end
-- local items = locations_to_items(locations)
gui.new_list_view({items = items, prompt = true, rowdata = true, api = ""})
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
gui.new_list_view({
items = items,
prompt = true,
ft = ft,
rowdata = true,
api = ""
})
-- if locations == nil or vim.tbl_isempty(locations) then
-- print "References not found"

@ -1,5 +1,9 @@
local gui = require "navigator.gui"
local ts_locals = require "nvim-treesitter.locals"
local ok, ts_locals = pcall(require, "nvim-treesitter.locals")
if not ok then error("treesitter not installed") end
local parsers = require "nvim-treesitter.parsers"
local ts_utils = require "nvim-treesitter.ts_utils"
local utils = require "nvim-treesitter.utils"
@ -70,26 +74,47 @@ local function prepare_node(node, kind)
return matches
end
local function get_smallest_context(source)
local scopes = ts_locals.get_scopes()
local function get_var_context(source)
local sbl, sbc, sel, sec = source:range()
local current = source
local result = current
local next = ts_utils.get_next_node(source)
local parent = current:parent()
while current ~= nil and not vim.tbl_contains(scopes, current) do
current = current:parent()
log(current)
log(current.node)
log(current:range())
-- local nod = prepare_node(current)
-- log(nod)
if next == nil or parent == nil then return end
if next:type() == "function" or next:type() == "arrow_function" then
log(current:type(), current:range())
return parent
else
return source
end
return current or nil
-- while current ~= nil do
-- log(current:type(), current:range())
-- if current:type() == "variable_declarator" or current:type() == "function_declaration" then
-- return current
-- end
-- -- local bl, bc, el, ec = current:range()
-- -- if bl == sbl and bc == sbc and el >= sel and ec >= sec then result = current end
-- current = current:parent()
-- end
-- log(current)
end
local function get_smallest_context(source)
local scopes = ts_locals.get_scopes()
local current = source
while current ~= nil and not vim.tbl_contains(scopes, current) do current = current:parent() end
log(current)
if current ~= nil then return current end
return get_var_context(source)
-- if source:type() == "identifier" then return get_var_context(source) end
end
local lsp_reference = require"navigator.dochighlight".goto_adjent_reference
function M.goto_adjacent_usage(bufnr, delta)
local opt = {forward = true}
log(delta)
-- log(delta)
if delta < 0 then opt = {forward = false} end
bufnr = bufnr or api.nvim_get_current_buf()
local node_at_point = ts_utils.get_node_at_cursor()
@ -132,7 +157,13 @@ local function get_all_nodes(bufnr, filter, summary)
-- Force some types to act like they are parents
-- instead of neighbors of the next nodes.
local containers = {["function"] = true, ["type"] = true, ["method"] = true}
local containers = {
["function"] = true,
["arrow_function"] = true,
["type"] = true,
["class"] = true,
["method"] = true
}
-- Step 2 find correct completions
local length = 10
local parents = {} -- stack of nodes a clever algorithm from treesiter refactor @Santos Gallegos
@ -156,20 +187,28 @@ local function get_all_nodes(bufnr, filter, summary)
item.kind = node.kind
item.type = node.type
local tsdata = node.def
local scope = get_smallest_context(tsdata)
log(item.type, tsdata:type())
if node.def == nil then goto continue end
local start_line_node, _, _ = tsdata:start()
item.range = ts_utils.node_to_lsp_range(tsdata)
item.node_text = ts_utils.get_node_text(tsdata, bufnr)[1]
local scope = get_smallest_context(tsdata)
if scope ~= nil then
-- it is strange..
log(item.node_text, item.kind, item.type)
item.node_scope = ts_utils.node_to_lsp_range(scope)
end
if filter ~= nil and not filter[item.type] then goto continue end
if summary then
table.insert(all_nodes, item)
if item.node_scope ~= nil then table.insert(all_nodes, item) end
goto continue
end
item.node_scope = scope
item.range = ts_utils.node_to_lsp_range(tsdata)
local start_line_node, _, _ = tsdata:start()
if item.node_text == "_" then goto continue end
item.full_text = vim.trim(api.nvim_buf_get_lines(bufnr, start_line_node, start_line_node + 1, false)[1] or "")
item.full_text = vim.trim(api.nvim_buf_get_lines(bufnr, start_line_node, start_line_node + 1,
false)[1] or "")
item.uri = uri
item.name = node.node_text
item.filename = fname
@ -180,24 +219,44 @@ local function get_all_nodes(bufnr, filter, summary)
local indent = ""
if #parents > 1 then indent = string.rep(" ", #parents - 1) .. "" end
item.text = string.format(" %s %s%-10s\t %s", item.kind, indent, item.node_text, item.full_text)
item.text = string.format(" %s %s%-10s\t %s", item.kind, indent, item.node_text,
item.full_text)
if #item.text > length then length = #item.text end
table.insert(all_nodes, item)
::continue::
end
end
verbose(all_nodes)
return all_nodes, length
end
function M.buf_func()
if ts_locals == nil then
function M.buf_func(bufnr)
if not ok or ts_locals == nil then
error("treesitter not loaded")
return
end
local bufnr = api.nvim_get_current_buf()
local all_nodes, width = get_all_nodes(bufnr, {["function"] = true, ["method"] = true}, true)
-- log(all_nodes, width)
bufnr = bufnr or api.nvim_get_current_buf()
local all_nodes, width = get_all_nodes(bufnr, {
["function"] = true,
["var"] = true,
["method"] = true,
["class"] = true,
["type"] = true
}, true)
table.sort(all_nodes, function(i, j)
if i.range and j.range then
if i.range.start.line == j.range.start.line then
return i.range['end'].line < j.range['end'].line
else
return i.range.start.line < j.range.start.line
end
end
return false
end)
verbose(all_nodes, width)
return all_nodes
end
@ -212,7 +271,14 @@ function M.buf_ts()
local all_nodes, width = get_all_nodes(bufnr)
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
gui.new_list_view({items = all_nodes, prompt = true, ft = ft, rawdata = true, width = width + 10, api = "🎄"})
gui.new_list_view({
items = all_nodes,
prompt = true,
ft = ft,
rawdata = true,
width = width + 10,
api = "🎄"
})
end
function M.bufs_ts()
@ -239,7 +305,13 @@ function M.bufs_ts()
verbose(ts_opened)
local ft = vim.api.nvim_buf_get_option(0, "ft")
gui.new_list_view({items = ts_opened, prompt = true, ft = ft, width = max_length + 10, api = "🎄"})
gui.new_list_view({
items = ts_opened,
prompt = true,
ft = ft,
width = max_length + 10,
api = "🎄"
})
end
end

@ -1,10 +1,7 @@
-- retreives data form file
-- and line to highlight
-- Some of function copied from https://github.com/RishabhRD/nvim-lsputils
local M = {
log_path = vim.lsp.get_log_path()
}
local M = {log_path = vim.lsp.get_log_path()}
function M.get_data_from_file(filename, startLine)
local displayLine
if startLine < 3 then
@ -28,10 +25,7 @@ function M.get_data_from_file(filename, startLine)
startLine = startLine + 1
end
end
return {
data = data,
line = displayLine
}
return {data = data, line = displayLine}
end
function M.get_base(path)
@ -47,9 +41,7 @@ end
local function getDir(path)
local data = {}
local len = #path
if len <= 1 then
return nil
end
if len <= 1 then return nil end
local last_index = 1
for i = 2, len do
local cur_char = path:sub(i, i)
@ -68,35 +60,22 @@ function M.get_relative_path(base_path, my_path)
local base_len = #base_data
local my_len = #my_data
if base_len > my_len then
return my_path
end
if base_len > my_len then return my_path end
if base_data[1] ~= my_data[1] then
return my_path
end
if base_data[1] ~= my_data[1] then return my_path end
local cur = 0
for i = 1, base_len do
if base_data[i] ~= my_data[i] then
break
end
if base_data[i] ~= my_data[i] then break end
cur = i
end
local data = ""
for i = cur + 1, my_len do
data = data .. my_data[i] .. "/"
end
for i = cur + 1, my_len do data = data .. my_data[i] .. "/" end
data = data .. M.get_base(my_path)
return data
end
local default_config = {
plugin = "navigator",
use_console = false,
use_file = true,
level = "debug"
}
local default_config = {plugin = "navigator", use_console = false, use_file = true, level = "error"}
M._log = require("guihua.log").new({level = default_config.level}, true)
@ -104,24 +83,16 @@ M._log = require("guihua.log").new({level = default_config.level}, true)
M.log = M._log.info
M.verbose = M._log.debug
function M.fmt(...)
M._log.fmt_info(...)
end
function M.fmt(...) M._log.fmt_info(...) end
function M.split(inputstr, sep)
if sep == nil then
sep = "%s"
end
if sep == nil then sep = "%s" end
local t = {}
for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do
table.insert(t, str)
end
for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do table.insert(t, str) end
return t
end
function M.trim_space(s)
return s:match("^%s*(.-)%s*$")
end
function M.trim_space(s) return s:match("^%s*(.-)%s*$") end
function M.quickfix_extract(line)
-- check if it is a line of file pos been selected
@ -137,7 +108,10 @@ function M.quickfix_extract(line)
M.log(line)
return nil
end
local location = {uri = "file:///" .. sep[1], range = {start = {line = sep[2] - 3 > 0 and sep[2] - 3 or 1}}}
local location = {
uri = "file:///" .. sep[1],
range = {start = {line = sep[2] - 3 > 0 and sep[2] - 3 or 1}}
}
location.range["end"] = {line = sep[2] + 15}
return location
end
@ -156,9 +130,7 @@ function M.getArgs(inputstr)
return cmd, t
end
function M.p(t)
print(vim.inspect(t))
end
function M.p(t) print(vim.inspect(t)) end
function M.printError(msg)
vim.cmd("echohl ErrorMsg")
@ -176,18 +148,14 @@ function M.open_log()
vim.cmd("edit " .. path)
end
function table.pack(...)
return {n = select("#", ...), ...}
end
function table.pack(...) return {n = select("#", ...), ...} end
function M.show(...)
local string = ""
local args = table.pack(...)
for i = 1, args.n do
string = string .. tostring(args[i]) .. "\t"
end
for i = 1, args.n do string = string .. tostring(args[i]) .. "\t" end
return string .. "\n"
end
@ -197,48 +165,26 @@ function M.split2(s, sep)
sep = sep or " "
local pattern = string.format("([^%s]+)", sep)
string.gsub(
s,
pattern,
function(c)
fields[#fields + 1] = c
end
)
string.gsub(s, pattern, function(c) fields[#fields + 1] = c end)
return fields
end
M.open_file = function(filename)
vim.api.nvim_command(string.format("e! %s", filename))
end
M.open_file = function(filename) vim.api.nvim_command(string.format("e! %s", filename)) end
M.open_file_at = function(filename, line, col)
vim.api.nvim_command(string.format("e! +%s %s", line, filename))
col = col or 1
vim.api.nvim_command(string.format("normal! %dl", col-1))
vim.api.nvim_command(string.format("normal! %dl", col - 1))
end
function M.exists(var)
for k, _ in pairs(_G) do
if k == var then
return true
end
end
end
function M.exists(var) for k, _ in pairs(_G) do if k == var then return true end end end
function M.partial(func, arg)
return (function(...)
return func(arg, ...)
end)
end
function M.partial(func, arg) return (function(...) return func(arg, ...) end) end
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
for i = 1, #exclude_ft do if string.find(fname, exclude_ft[i]) then return true end end
return false
end
@ -250,33 +196,28 @@ local api = vim.api
local bufs
function M.set_virt_eol(bufnr, lnum, chunks, priority, id)
if nss == nil then
nss = api.nvim_create_namespace("navigator_search")
end
if nss == nil then 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
return api.nvim_buf_set_extmark(bufnr, nss, lnum, -1, {id = id, virt_text = chunks, priority = priority})
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
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
-- 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
for bufnr in pairs(bufs) do M.clear_buf(bufnr) end
bufs = {}
end

Loading…
Cancel
Save