feat(util): util method to check if ts lang is available on any Neovim version. See #1422

This commit is contained in:
Folke Lemaitre 2025-02-25 15:25:48 +01:00
parent b0f983ef9a
commit e2cb9df7d0
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
5 changed files with 19 additions and 29 deletions

View file

@ -128,7 +128,7 @@ function M.has_lang(langs)
local ret = {} ---@type table<string, boolean>
local available, missing = {}, {} ---@type string[], string[]
for _, lang in ipairs(langs) do
local has_lang = pcall(vim.treesitter.get_string_parser, "", lang)
local has_lang = Snacks.util.get_lang(lang) ~= nil
ret[lang] = has_lang
lang = ("`%s`"):format(lang)
if has_lang then

View file

@ -277,7 +277,7 @@ function M:highlight(opts)
})
end
self:check_big()
local lang = Snacks.picker.highlight.get_lang({ lang = opts.lang, ft = ft })
local lang = Snacks.util.get_lang(opts.lang or ft)
if not (lang and pcall(vim.treesitter.start, self.win.buf, lang)) and ft then
vim.bo[self.win.buf].syntax = ft
end

View file

@ -3,19 +3,6 @@ local M = {}
M.langs = {} ---@type table<string, boolean>
---@param opts? {lang?:string, ft?:string}
function M.get_lang(opts)
opts = opts or {}
local lang = opts.lang or (opts.ft and vim.treesitter.language.get_lang(opts.ft)) or nil
if not lang then
return
end
if M.langs[lang] == nil then
M.langs[lang] = pcall(vim.treesitter.language.add, lang)
end
return M.langs[lang] and lang or nil
end
---@param opts? {buf?:number, code?:string, ft?:string, lang?:string, file?:string, extmarks?:boolean}
function M.get_highlights(opts)
opts = opts or {}
@ -28,7 +15,7 @@ function M.get_highlights(opts)
or (opts.buf and vim.bo[opts.buf].filetype)
or (opts.file and vim.filetype.match({ filename = opts.file, buf = 0 }))
or vim.bo.filetype
local lang = M.get_lang({ lang = opts.lang, ft = ft })
local lang = Snacks.util.get_lang(opts.lang or ft)
local parser ---@type vim.treesitter.LanguageTree?
if lang then
lang = lang:lower()

View file

@ -315,18 +315,6 @@ end
local TSScope = setmetatable({}, Scope)
TSScope.__index = TSScope
function TSScope.has_ts(buf)
if vim.b[buf].snacks_ts == nil then
if vim.b[buf].ts_highlight then
vim.b[buf].snacks_ts = true
else
local ok, parser = pcall(vim.treesitter.get_parser, buf)
vim.b[buf].snacks_ts = ok and parser ~= nil
end
end
return vim.b[buf].snacks_ts
end
-- Expand the scope to fill the range of the node
function TSScope:fill()
local n = self.node
@ -513,7 +501,7 @@ function M.get(cb, opts)
end
---@type snacks.scope.Scope
local Class = (opts.treesitter.enabled and TSScope.has_ts(opts.buf)) and TSScope or IndentScope
local Class = (opts.treesitter.enabled and Snacks.util.get_lang(opts.buf)) and TSScope or IndentScope
if rawequal(Class, TSScope) and opts.parse ~= false then
TSScope:init(function()
opts.parse = false

View file

@ -9,6 +9,7 @@ M.is_win = jit.os:find("Windows")
local uv = vim.uv or vim.loop
local key_cache = {} ---@type table<string, string>
local langs = {} ---@type table<string, boolean>
---@alias snacks.util.hl table<string, string|vim.api.keyset.highlight>
@ -22,6 +23,20 @@ vim.api.nvim_create_autocmd("ColorScheme", {
end,
})
---@param lang string|number|nil
---@overload fun(buf:number):string?
---@overload fun(ft:string):string?
---@return string?
function M.get_lang(lang)
lang = type(lang) == "number" and vim.bo[lang].filetype or lang --[[@as string?]]
lang = lang and vim.treesitter.language.get_lang(lang) or lang
if lang and lang ~= "" and langs[lang] == nil then
local ok, ret = pcall(vim.treesitter.language.add, lang)
langs[lang] = (ok and ret) or (ok and vim.fn.has("nvim-0.11") == 0)
end
return langs[lang] and lang or nil
end
--- Ensures the hl groups are always set, even after a colorscheme change.
---@param groups snacks.util.hl
---@param opts? { prefix?:string, default?:boolean, managed?:boolean }