diff options
| author | Mike Vink <mike@pionative.com> | 2025-01-19 13:52:52 +0100 |
|---|---|---|
| committer | Mike Vink <mike@pionative.com> | 2025-01-19 13:52:52 +0100 |
| commit | b77413ff8f59f380612074f0c9bd49093d8db695 (patch) | |
| tree | 32c39a811ba96ed4ab0a1c81cce9f8d518ed7e31 /lua/blink/cmp/sources/snippets/default/scan.lua | |
Squashed 'mut/neovim/pack/plugins/start/blink.cmp/' content from commit 1cc3b1a
git-subtree-dir: mut/neovim/pack/plugins/start/blink.cmp
git-subtree-split: 1cc3b1a908fbcfd15451c4772759549724f38524
Diffstat (limited to 'lua/blink/cmp/sources/snippets/default/scan.lua')
| -rw-r--r-- | lua/blink/cmp/sources/snippets/default/scan.lua | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lua/blink/cmp/sources/snippets/default/scan.lua b/lua/blink/cmp/sources/snippets/default/scan.lua new file mode 100644 index 0000000..6971691 --- /dev/null +++ b/lua/blink/cmp/sources/snippets/default/scan.lua @@ -0,0 +1,94 @@ +local utils = require('blink.cmp.sources.snippets.utils') +local scan = {} + +function scan.register_snippets(search_paths) + local registry = {} + + for _, path in ipairs(search_paths) do + local files = scan.load_package_json(path) or scan.scan_for_snippets(path) + for ft, file in pairs(files) do + local key + if type(ft) == 'number' then + key = vim.fn.fnamemodify(files[ft], ':t:r') + else + key = ft + end + + if not key then return end + + registry[key] = registry[key] or {} + if type(file) == 'table' then + vim.list_extend(registry[key], file) + else + table.insert(registry[key], file) + end + end + end + + return registry +end + +---@type fun(self: utils, dir: string, result?: string[]): string[] +---@return string[] +function scan.scan_for_snippets(dir, result) + result = result or {} + + local stat = vim.uv.fs_stat(dir) + if not stat then return result end + + if stat.type == 'directory' then + local req = vim.uv.fs_scandir(dir) + if not req then return result end + + local function iter() return vim.uv.fs_scandir_next(req) end + + for name, ftype in iter do + local path = string.format('%s/%s', dir, name) + + if ftype == 'directory' then + result[name] = scan.scan_for_snippets(path, result[name] or {}) + else + scan.scan_for_snippets(path, result) + end + end + elseif stat.type == 'file' then + local name = vim.fn.fnamemodify(dir, ':t') + + if name:match('%.json$') then table.insert(result, dir) end + elseif stat.type == 'link' then + local target = vim.uv.fs_readlink(dir) + + if target then scan.scan_for_snippets(target, result) end + end + + return result +end + +--- This will try to load the snippets from the package.json file +---@param path string +function scan.load_package_json(path) + local file = path .. '/package.json' + -- todo: ideally this is async, although it takes 0.5ms on my system so it might not matter + local data = utils.read_file(file) + if not data then return end + + local pkg = require('blink.cmp.sources.snippets.utils').parse_json_with_error_msg(file, data) + + ---@type {path: string, language: string|string[]}[] + local snippets = vim.tbl_get(pkg, 'contributes', 'snippets') + if not snippets then return end + + local ret = {} ---@type table<string, string[]> + for _, s in ipairs(snippets) do + local langs = s.language or {} + langs = type(langs) == 'string' and { langs } or langs + ---@cast langs string[] + for _, lang in ipairs(langs) do + ret[lang] = ret[lang] or {} + table.insert(ret[lang], vim.fs.normalize(vim.fs.joinpath(path, s.path))) + end + end + return ret +end + +return scan |
