Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
glepnir committed Jan 18, 2025
1 parent 92fb708 commit c3256b2
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 118 deletions.
2 changes: 2 additions & 0 deletions init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ _G.program_ft = {
'json',
'cmake',
'html',
'markdown',
'text',
}
_G.is_mac = vim.uv.os_uname().sysname == 'Darwin'

Expand Down
73 changes: 7 additions & 66 deletions lua/internal/completion.lua
Original file line number Diff line number Diff line change
Expand Up @@ -54,71 +54,12 @@ au('LspAttach', {
end,
})

local function feedkeys(key)
api.nvim_feedkeys(api.nvim_replace_termcodes(key, true, false, true), 'n', true)
end

local function buf_has_client(bufnr)
return #lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_completion }) > 0
end

local function is_path_related(line, col)
if col == 0 then
return false
end
local char_before_cursor = line:sub(col, col)
return char_before_cursor:match('[/%w_%-%.~]')
end

local debounce_fn = function()
local timer = nil --[[uv_timer_t]]
local function safe_close()
if timer and not timer:is_closing() then
timer:stop()
timer:close()
timer = nil
end
end

return function(key)
safe_close()
timer = assert(vim.uv.new_timer())
local row, col = unpack(api.nvim_win_get_cursor(0))
timer:start(50, 0, function()
safe_close()
vim.schedule(function()
local curpos = api.nvim_win_get_cursor(0)
if curpos[1] ~= row and curpos[2] ~= col + 1 then
return
end
feedkeys(key)
end)
end)
end
end

local debounce_feedkey = debounce_fn()

-- completion for directory and files
au(InsertCharPre, {
callback = function(args)
if pumvisible() then
return
end
local bufnr = args.buf
local ok = vim.iter({ 'terminal', 'prompt', 'help' }):any(function(v)
return v == vim.bo[bufnr].buftype
end)
if ok then
return
end
local char = vim.v.char
local lnum, col = unpack(api.nvim_win_get_cursor(0))
local line_text = ffi.string(ffi.C.ml_get(lnum))
if char == '/' and is_path_related(line_text, col) then
feedkeys('<C-X><C-F>')
elseif char:match('%w') and not buf_has_client(bufnr) then
debounce_feedkey('<C-X><C-N>')
end
au('FileType', {
callback = function()
vim.lsp.start({
name = 'wordpath',
cmd = require('internal.server').create(),
root_dir = vim.uv.cwd(),
})
end,
})
12 changes: 0 additions & 12 deletions lua/internal/event.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,3 @@ au('CmdlineLeave', {
})
end,
})

-- au('FileType', {
-- group = group,
-- pattern = 'lua',
-- callback = function()
-- vim.lsp.start({
-- name = 'MineServer',
-- cmd = require('internal.server').create(),
-- root_dir = vim.uv.cwd(),
-- })
-- end,
-- })
139 changes: 100 additions & 39 deletions lua/internal/server.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
local server = {}

local client_capabilities = {}

local projects = {}

---@return table
Expand All @@ -16,6 +14,49 @@ local function get_root(filename)
return data
end

---@param path string
---@param callback function
local function scan_dir_async(path, callback)
local co = coroutine.create(function(resolve)
local handle = vim.uv.fs_scandir(path)
if not handle then
resolve({})
return
end

local results = {}
while true do
local name, type = vim.uv.fs_scandir_next(handle)
if not name then
break
end

local is_hidden = name:match('^%.')
if type == 'directory' and not name:match('/$') then
name = name .. '/'
end

table.insert(results, {
name = name,
type = type,
is_hidden = is_hidden,
})
end

resolve(results)
end)

coroutine.resume(co, callback)
end

---@param path string
---@param callback function
local function check_path_exists_async(path, callback)
vim.uv.fs_stat(path, function(err, stats)
callback(not err and stats ~= nil)
end)
end

function server.create()
return function()
local srv = {}
Expand All @@ -26,7 +67,6 @@ function server.create()
projects[params.rootPath] = {}
end
client_capabilities[client_id] = params.capabilities

callback(nil, {
capabilities = {
completionProvider = {
Expand All @@ -46,57 +86,79 @@ function server.create()
local position = params.position
local filename = uri:gsub('file://', '')
local root = get_root(filename)

if not root then
return nil
callback(nil, { items = {} })
return
end

local line = root[filename][position.line + 1]
if not line then
callback(nil, { items = {} })
return
end

local prefix = line:sub(1, position.character)
local is_literal = prefix:find('"')
if is_literal then
prefix = prefix:sub(is_literal + 1, position.character)
end
local dir_part = prefix:match('^(.*/)[^/]*$')

-- handle path completion
local last_slash = prefix:match('.*(/[^/]*)$')
if last_slash == '/' then
local dir_part = prefix:match('^(.*/)[^/]*$') or './'
local results = vim.fn.getcompletion(dir_part, 'file', true)
if not dir_part then
callback(nil, { items = {} })
return
end

if next(results) == nil then
local expanded_path = vim.fs.normalize(dir_part)

check_path_exists_async(expanded_path, function(exists)
if not exists then
callback(nil, { items = {} })
return
end

local items = {}
for _, path in ipairs(results) do
local label = path:gsub(dir_part, ''):gsub('/', '')
table.insert(items, {
label = label,
kind = 17,
textEdit = {
range = {
start = { line = position.line, character = position.character },
['end'] = { line = position.line, character = position.character },
},
newText = label,
},
})
end

callback(nil, {
isIncomplete = false,
items = items,
})
end
scan_dir_async(expanded_path, function(results)
local items = {}
local current_input = prefix:match('[^/]*$') or ''

for _, entry in ipairs(results) do
local name = entry.name
if vim.startswith(name:lower(), current_input:lower()) then
local kind = entry.type == 'directory' and 19 or 17 -- 19 for folder, 17 for file
local label = name
if entry.type == 'directory' then
label = label:gsub('/$', '')
elseif label:match('^.') then
label = label:gsub('^.', '')
end

table.insert(items, {
label = label,
kind = kind,
insertText = label,
filterText = label,
detail = entry.is_hidden and '(Hidden)' or nil,
sortText = string.format('%d%s', entry.is_hidden and 1 or 0, label:lower()),
})
end
end

vim.schedule(function()
callback(nil, {
isIncomplete = false,
items = items,
})
end)
end)
end)
end

srv['textDocument/completion'] = srv.completion

srv['textDocument/didOpen'] = function(params)
local filename = params.textDocument.uri:gsub('file://', '')
local data
for r, item in pairs(projects) do
if vim.startswith(filename, r) then
data = item
break
end
end
local data = get_root(filename)
if not data then
return
end
Expand All @@ -115,7 +177,6 @@ function server.create()
callback(nil, nil)
end

-- create rpc object
return {
request = function(method, params, callback)
if srv[method] then
Expand Down
3 changes: 2 additions & 1 deletion lua/modules/lsp/config.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local au = vim.api.nvim_create_autocmd
local lspconfig = require('lspconfig')

vim.api.nvim_create_autocmd('LspAttach', {
au('LspAttach', {
callback = function(args)
local client = vim.lsp.get_clients({ id = args.data.client_id })[1]
client.server_capabilities.semanticTokensProvider = nil
Expand Down

0 comments on commit c3256b2

Please sign in to comment.