diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..2af0068
--- /dev/null
+++ b/TODO.md
@@ -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)
diff --git a/lua/navigator.lua b/lua/navigator.lua
index b62356f..e70fe10 100644
--- a/lua/navigator.lua
+++ b/lua/navigator.lua
@@ -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)
diff --git a/lua/navigator/definition.lua b/lua/navigator/definition.lua
index 88b3dad..90de38d 100644
--- a/lua/navigator/definition.lua
+++ b/lua/navigator/definition.lua
@@ -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)
diff --git a/lua/navigator/gui.lua b/lua/navigator/gui.lua
index 417afa0..b4e2fcf 100644
--- a/lua/navigator/gui.lua
+++ b/lua/navigator/gui.lua
@@ -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 = {
},
+ 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"
+--
+]]
diff --git a/lua/navigator/hierarchy.lua b/lua/navigator/hierarchy.lua
index f359a91..2186b62 100644
--- a/lua/navigator/hierarchy.lua
+++ b/lua/navigator/hierarchy.lua
@@ -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)
diff --git a/lua/navigator/implementation.lua b/lua/navigator/implementation.lua
index 4c8f36f..3a5b150 100644
--- a/lua/navigator/implementation.lua
+++ b/lua/navigator/implementation.lua
@@ -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)
diff --git a/lua/navigator/lspclient/attach.lua b/lua/navigator/lspclient/attach.lua
index baa62ba..ec39633 100644
--- a/lua/navigator/lspclient/attach.lua
+++ b/lua/navigator/lspclient/attach.lua
@@ -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
diff --git a/lua/navigator/lspclient/clients.lua b/lua/navigator/lspclient/clients.lua
index b160b5c..e6174fb 100644
--- a/lua/navigator/lspclient/clients.lua
+++ b/lua/navigator/lspclient/clients.lua
@@ -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
diff --git a/lua/navigator/lspclient/lspkind.lua b/lua/navigator/lspclient/lspkind.lua
index c8051ec..7cf37dc 100644
--- a/lua/navigator/lspclient/lspkind.lua
+++ b/lua/navigator/lspclient/lspkind.lua
@@ -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
diff --git a/lua/navigator/lspclient/mapping.lua b/lua/navigator/lspclient/mapping.lua
index 47d9341..96fdd11 100644
--- a/lua/navigator/lspclient/mapping.lua
+++ b/lua/navigator/lspclient/mapping.lua
@@ -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 = "", func = "signature_help()"},
{key = "gs", func = "signature_help()"}, {key = "g0", func = "document_symbol()"},
{key = "gW", func = "workspace_symbol()"}, {key = "", 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 = "re", func = "rename()"}, {key = "gi", func = "incoming_calls()"},
- {key = "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 = "re", func = "rename()"},
+ {key = "gi", func = "incoming_calls()"}, {key = "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 lua vim.lsp.buf.formatting()]])
end
-- if user_opts.cap.document_range_formatting then
- if range_fmt then buf_set_keymap("v", "ff", "lua vim.lsp.buf.range_formatting()", opts) end
+ if range_fmt then
+ buf_set_keymap("v", "ff", "lua vim.lsp.buf.range_formatting()", 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 .. " silent! " .. f
+ local cmd = "autocmd FileType " .. file_types .. " autocmd nvim_lsp_autos " .. value.ev ..
+ " 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
diff --git a/lua/navigator/lspwrapper.lua b/lua/navigator/lspwrapper.lua
index 8139ca4..c8d5088 100644
--- a/lua/navigator/lspwrapper.lua
+++ b/lua/navigator/lspwrapper.lua
@@ -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
diff --git a/lua/navigator/reference.lua b/lua/navigator/reference.lua
index 678502c..9c57b02 100644
--- a/lua/navigator/reference.lua
+++ b/lua/navigator/reference.lua
@@ -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}
diff --git a/lua/navigator/symbols.lua b/lua/navigator/symbols.lua
index ddd7167..2934071 100644
--- a/lua/navigator/symbols.lua
+++ b/lua/navigator/symbols.lua
@@ -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"
diff --git a/lua/navigator/treesitter.lua b/lua/navigator/treesitter.lua
index 6a435c3..f087996 100644
--- a/lua/navigator/treesitter.lua
+++ b/lua/navigator/treesitter.lua
@@ -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
diff --git a/lua/navigator/util.lua b/lua/navigator/util.lua
index 1abff5c..824fca4 100644
--- a/lua/navigator/util.lua
+++ b/lua/navigator/util.lua
@@ -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