summaryrefslogtreecommitdiff
path: root/lua/blink/cmp/sources/snippets/default/scan.lua
diff options
context:
space:
mode:
authorMike Vink <mike@pionative.com>2025-01-19 13:52:52 +0100
committerMike Vink <mike@pionative.com>2025-01-19 13:52:52 +0100
commitb77413ff8f59f380612074f0c9bd49093d8db695 (patch)
tree32c39a811ba96ed4ab0a1c81cce9f8d518ed7e31 /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.lua94
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