feat(treesitter): upstream query omnifunc from playground (#23394)

and set by default in `ftplugin/query.lua`
This commit is contained in:
Christian Clason 2023-04-30 11:01:54 +02:00 committed by GitHub
parent fa20c12ba3
commit 668f16bac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 6 deletions

View File

@ -37,6 +37,7 @@ The following new APIs or features were added.
• |vim.iter()| provides a generic iterator interface for tables and Lua
iterators |luaref-in|.
• Added |vim.keycode()| for translating keycodes in a string.
• Added automatic linting of treesitter query files (see |ft-query-plugin|).
@ -45,6 +46,9 @@ iterators |luaref-in|.
<
• Enabled treesitter highlighting for treesitter query files by default.
• Added |vim.treesitter.query.omnifunc()| for treesitter query files (set by
default).
==============================================================================
CHANGED FEATURES *news-changed*

View File

@ -853,7 +853,7 @@ lint({buf}, {opts}) *vim.treesitter.query.lint()*
The found diagnostics are reported using |diagnostic-api|. By default, the
parser used for verification is determined by the containing folder of the
query file, e.g., if the path is `**/lua/highlights.scm` , the parser for the `lua` language will be used.
query file, e.g., if the path ends in `/lua/highlights.scm` , the parser for the `lua` language will be used.
Parameters: ~
• {buf} (integer) Buffer handle
@ -875,6 +875,13 @@ list_predicates() *vim.treesitter.query.list_predicates()*
Return: ~
string[] List of supported predicates.
omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()*
Omnifunc for completing node names and predicates in treesitter queries.
Use via >lua
vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
<
parse({lang}, {query}) *vim.treesitter.query.parse()*
Parse {query} as a string. (If the query is in a file, the caller should
read the contents into a string before calling).

View File

@ -11,6 +11,9 @@ end
-- use treesitter over syntax
vim.treesitter.start()
-- set omnifunc
vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
-- query linter
local buf = vim.api.nvim_get_current_buf()
local query_lint_on = vim.g.query_lint_on or { 'BufEnter', 'BufWrite' }

View File

@ -1,4 +1,6 @@
local namespace = vim.api.nvim_create_namespace('vim.treesitter.query_linter')
local api = vim.api
local namespace = api.nvim_create_namespace('vim.treesitter.query_linter')
-- those node names exist for every language
local BUILT_IN_NODE_NAMES = { '_', 'ERROR' }
@ -49,7 +51,7 @@ end
--- @param buf integer
--- @return string?
local function guess_query_lang(buf)
local filename = vim.api.nvim_buf_get_name(buf)
local filename = api.nvim_buf_get_name(buf)
if filename ~= '' then
local ok, query_lang = pcall(vim.fn.fnamemodify, filename, ':p:h:t')
if ok then
@ -256,7 +258,7 @@ end
--- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting
function M.lint(buf, opts)
if buf == 0 then
buf = vim.api.nvim_get_current_buf()
buf = api.nvim_get_current_buf()
end
local diagnostics = {}
@ -299,4 +301,56 @@ function M.clear(buf)
vim.diagnostic.reset(namespace, buf)
end
--- @private
--- @param findstart integer
--- @param base string
function M.omnifunc(findstart, base)
if findstart == 1 then
local result =
api.nvim_get_current_line():sub(1, api.nvim_win_get_cursor(0)[2]):find('["#%-%w]*$')
return result - 1
end
local buf = api.nvim_get_current_buf()
local query_lang = guess_query_lang(buf)
local ok, parser_info = pcall(vim.treesitter.language.inspect, query_lang)
if not ok then
return -2
end
local items = {}
for _, f in pairs(parser_info.fields) do
if f:find(base, 1, true) then
table.insert(items, f .. ':')
end
end
for _, p in pairs(vim.treesitter.query.list_predicates()) do
local text = '#' .. p
local found = text:find(base, 1, true)
if found and found <= 2 then -- with or without '#'
table.insert(items, text)
end
text = '#not-' .. p
found = text:find(base, 1, true)
if found and found <= 2 then -- with or without '#'
table.insert(items, text)
end
end
for _, p in pairs(vim.treesitter.query.list_directives()) do
local text = '#' .. p
local found = text:find(base, 1, true)
if found and found <= 2 then -- with or without '#'
table.insert(items, text)
end
end
for _, s in pairs(parser_info.symbols) do
local text = s[2] and s[1] or '"' .. s[1]:gsub([[\]], [[\\]]) .. '"'
if text:find(base, 1, true) then
table.insert(items, text)
end
end
return { words = items, refresh = 'always' }
end
return M

View File

@ -728,7 +728,7 @@ end
---
--- The found diagnostics are reported using |diagnostic-api|.
--- By default, the parser used for verification is determined by the containing folder
--- of the query file, e.g., if the path is `**/lua/highlights.scm`, the parser for the
--- of the query file, e.g., if the path ends in `/lua/highlights.scm`, the parser for the
--- `lua` language will be used.
---@param buf (integer) Buffer handle
---@param opts (QueryLinterOpts|nil) Optional keyword arguments:
@ -743,4 +743,14 @@ function M.lint(buf, opts)
end
end
--- Omnifunc for completing node names and predicates in treesitter queries.
---
--- Use via
--- <pre>lua
--- vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
--- </pre>
function M.omnifunc(findstart, base)
return require('vim.treesitter._query_linter').omnifunc(findstart, base)
end
return M