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 • |vim.iter()| provides a generic iterator interface for tables and Lua
iterators |luaref-in|. iterators |luaref-in|.
• Added |vim.keycode()| for translating keycodes in a string. • Added |vim.keycode()| for translating keycodes in a string.
• Added automatic linting of treesitter query files (see |ft-query-plugin|). • 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. • 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* 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 The found diagnostics are reported using |diagnostic-api|. By default, the
parser used for verification is determined by the containing folder of 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: ~ Parameters: ~
• {buf} (integer) Buffer handle • {buf} (integer) Buffer handle
@ -875,6 +875,13 @@ list_predicates() *vim.treesitter.query.list_predicates()*
Return: ~ Return: ~
string[] List of supported predicates. 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({lang}, {query}) *vim.treesitter.query.parse()*
Parse {query} as a string. (If the query is in a file, the caller should Parse {query} as a string. (If the query is in a file, the caller should
read the contents into a string before calling). read the contents into a string before calling).

View File

@ -11,6 +11,9 @@ end
-- use treesitter over syntax -- use treesitter over syntax
vim.treesitter.start() vim.treesitter.start()
-- set omnifunc
vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
-- query linter -- query linter
local buf = vim.api.nvim_get_current_buf() local buf = vim.api.nvim_get_current_buf()
local query_lint_on = vim.g.query_lint_on or { 'BufEnter', 'BufWrite' } 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 -- those node names exist for every language
local BUILT_IN_NODE_NAMES = { '_', 'ERROR' } local BUILT_IN_NODE_NAMES = { '_', 'ERROR' }
@ -49,7 +51,7 @@ end
--- @param buf integer --- @param buf integer
--- @return string? --- @return string?
local function guess_query_lang(buf) 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 if filename ~= '' then
local ok, query_lang = pcall(vim.fn.fnamemodify, filename, ':p:h:t') local ok, query_lang = pcall(vim.fn.fnamemodify, filename, ':p:h:t')
if ok then if ok then
@ -256,7 +258,7 @@ end
--- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting --- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting
function M.lint(buf, opts) function M.lint(buf, opts)
if buf == 0 then if buf == 0 then
buf = vim.api.nvim_get_current_buf() buf = api.nvim_get_current_buf()
end end
local diagnostics = {} local diagnostics = {}
@ -299,4 +301,56 @@ function M.clear(buf)
vim.diagnostic.reset(namespace, buf) vim.diagnostic.reset(namespace, buf)
end 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 return M

View File

@ -728,7 +728,7 @@ end
--- ---
--- The found diagnostics are reported using |diagnostic-api|. --- The found diagnostics are reported using |diagnostic-api|.
--- By default, the parser used for verification is determined by the containing folder --- 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. --- `lua` language will be used.
---@param buf (integer) Buffer handle ---@param buf (integer) Buffer handle
---@param opts (QueryLinterOpts|nil) Optional keyword arguments: ---@param opts (QueryLinterOpts|nil) Optional keyword arguments:
@ -743,4 +743,14 @@ function M.lint(buf, opts)
end end
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 return M