summaryrefslogtreecommitdiff
path: root/lua/blink/cmp/sources/path/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/blink/cmp/sources/path/init.lua')
-rw-r--r--lua/blink/cmp/sources/path/init.lua89
1 files changed, 89 insertions, 0 deletions
diff --git a/lua/blink/cmp/sources/path/init.lua b/lua/blink/cmp/sources/path/init.lua
new file mode 100644
index 0000000..bb5f508
--- /dev/null
+++ b/lua/blink/cmp/sources/path/init.lua
@@ -0,0 +1,89 @@
+-- credit to https://github.com/hrsh7th/cmp-path for the original implementation
+-- and https://codeberg.org/FelipeLema/cmp-async-path for the async implementation
+
+--- @class blink.cmp.PathOpts
+--- @field trailing_slash boolean
+--- @field label_trailing_slash boolean
+--- @field get_cwd fun(context: blink.cmp.Context): string
+--- @field show_hidden_files_by_default boolean
+
+--- @class blink.cmp.Source
+--- @field opts blink.cmp.PathOpts
+local path = {}
+
+function path.new(opts)
+ local self = setmetatable({}, { __index = path })
+
+ --- @type blink.cmp.PathOpts
+ opts = vim.tbl_deep_extend('keep', opts, {
+ trailing_slash = true,
+ label_trailing_slash = true,
+ get_cwd = function(context) return vim.fn.expand(('#%d:p:h'):format(context.bufnr)) end,
+ show_hidden_files_by_default = false,
+ })
+ require('blink.cmp.config.utils').validate('sources.providers.path', {
+ trailing_slash = { opts.trailing_slash, 'boolean' },
+ label_trailing_slash = { opts.label_trailing_slash, 'boolean' },
+ get_cwd = { opts.get_cwd, 'function' },
+ show_hidden_files_by_default = { opts.show_hidden_files_by_default, 'boolean' },
+ }, opts)
+
+ self.opts = opts
+ return self
+end
+
+function path:get_trigger_characters() return { '/', '.' } end
+
+function path:get_completions(context, callback)
+ -- we use libuv, but the rest of the library expects to be synchronous
+ callback = vim.schedule_wrap(callback)
+
+ local lib = require('blink.cmp.sources.path.lib')
+
+ local dirname = lib.dirname(self.opts.get_cwd, context)
+ if not dirname then return callback({ is_incomplete_forward = false, is_incomplete_backward = false, items = {} }) end
+
+ local include_hidden = self.opts.show_hidden_files_by_default
+ or (string.sub(context.line, context.bounds.start_col, context.bounds.start_col) == '.' and context.bounds.length == 0)
+ or (
+ string.sub(context.line, context.bounds.start_col - 1, context.bounds.start_col - 1) == '.'
+ and context.bounds.length > 0
+ )
+ lib
+ .candidates(context, dirname, include_hidden, self.opts)
+ :map(
+ function(candidates)
+ callback({ is_incomplete_forward = false, is_incomplete_backward = false, items = candidates })
+ end
+ )
+ :catch(function() callback() end)
+end
+
+function path:resolve(item, callback)
+ require('blink.cmp.sources.path.fs')
+ .read_file(item.data.full_path, 1024)
+ :map(function(content)
+ local is_binary = content:find('\0')
+
+ -- binary file
+ if is_binary then
+ item.documentation = {
+ kind = 'plaintext',
+ value = 'Binary file',
+ }
+ -- highlight with markdown
+ else
+ local ext = vim.fn.fnamemodify(item.data.path, ':e')
+ item.documentation = {
+ kind = 'markdown',
+ value = '```' .. ext .. '\n' .. content .. '```',
+ }
+ end
+
+ return item
+ end)
+ :map(function(resolved_item) callback(resolved_item) end)
+ :catch(function() callback(item) end)
+end
+
+return path