diff --git a/lua/blink/cmp/sources/path/init.lua b/lua/blink/cmp/sources/path/init.lua index 7af87e43..bcc694e7 100644 --- a/lua/blink/cmp/sources/path/init.lua +++ b/lua/blink/cmp/sources/path/init.lua @@ -44,7 +44,7 @@ function path:get_completions(context, callback) and context.bounds.length > 0 ) lib - .candidates(dirname, include_hidden, self.opts) + .candidates(context, dirname, include_hidden, self.opts) :map( function(candidates) callback({ is_incomplete_forward = false, is_incomplete_backward = false, items = candidates }) diff --git a/lua/blink/cmp/sources/path/lib.lua b/lua/blink/cmp/sources/path/lib.lua index a54c2578..d8ff24de 100644 --- a/lua/blink/cmp/sources/path/lib.lua +++ b/lua/blink/cmp/sources/path/lib.lua @@ -43,10 +43,11 @@ function lib.dirname(path_regex, get_cwd, context) return nil end +--- @param context blink.cmp.Context --- @param dirname string --- @param include_hidden boolean --- @param opts table -function lib.candidates(dirname, include_hidden, opts) +function lib.candidates(context, dirname, include_hidden, opts) local fs = require('blink.cmp.sources.path.fs') return fs.scan_dir_async(dirname) :map(function(entries) return fs.fs_stat_all(dirname, entries) end) @@ -54,7 +55,10 @@ function lib.candidates(dirname, include_hidden, opts) return vim.tbl_filter(function(entry) return include_hidden or entry.name:sub(1, 1) ~= '.' end, entries) end) :map(function(entries) - return vim.tbl_map(function(entry) return lib.entry_to_completion_item(entry, dirname, opts) end, entries) + return vim.tbl_map( + function(entry) return lib.entry_to_completion_item(context, entry, dirname, opts) end, + entries + ) end) end @@ -67,20 +71,42 @@ function lib.is_slash_comment() return is_slash_comment and not no_filetype end +--- @param context blink.cmp.Context --- @param entry { name: string, type: string, stat: table } --- @param dirname string --- @param opts table --- @return blink.cmp.CompletionItem[] -function lib.entry_to_completion_item(entry, dirname, opts) +function lib.entry_to_completion_item(context, entry, dirname, opts) local is_dir = entry.type == 'directory' local CompletionItemKind = require('blink.cmp.types').CompletionItemKind + local insert_text = is_dir and entry.name .. '/' or entry.name return { label = (opts.label_trailing_slash and is_dir) and entry.name .. '/' or entry.name, kind = is_dir and CompletionItemKind.Folder or CompletionItemKind.File, - insertText = is_dir and entry.name .. '/' or entry.name, + insertText = insert_text, + textEdit = lib.get_text_edit(context, insert_text), word = opts.trailing_slash and entry.name or nil, data = { path = entry.name, full_path = dirname .. '/' .. entry.name, type = entry.type, stat = entry.stat }, } end +--- @param insert_text string +--- @param context blink.cmp.Context +--- @return lsp.Range | nil +function lib.get_text_edit(context, insert_text) + local line_before_cursor = context.line:sub(1, context.cursor[2]) + + local parts = vim.split(line_before_cursor, '/') + local last_part = parts[#parts] + + -- TODO: return the insert and replace ranges, instaed of only the insert range + return { + newText = insert_text, + range = { + start = { line = context.cursor[1] - 1, character = context.cursor[2] - #last_part }, + ['end'] = { line = context.cursor[1] - 1, character = context.cursor[2] }, + }, + } +end + return lib