1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
local a = vim.api
local query = require('vim.treesitter.query')
local language = require('vim.treesitter.language')
local LanguageTree = require('vim.treesitter.languagetree')
-- TODO(bfredl): currently we retain parsers for the lifetime of the buffer.
-- Consider use weak references to release parser if all plugins are done with
-- it.
local parsers = {}
local M = vim.tbl_extend('error', query, language)
M.language_version = vim._ts_get_language_version()
M.minimum_language_version = vim._ts_get_minimum_language_version()
setmetatable(M, {
__index = function(t, k)
if k == 'highlighter' then
t[k] = require('vim.treesitter.highlighter')
return t[k]
elseif k == 'language' then
t[k] = require('vim.treesitter.language')
return t[k]
elseif k == 'query' then
t[k] = require('vim.treesitter.query')
return t[k]
end
end,
})
--- Creates a new parser.
---
--- It is not recommended to use this, use vim.treesitter.get_parser() instead.
---
---@param bufnr The buffer the parser will be tied to
---@param lang The language of the parser
---@param opts Options to pass to the created language tree
function M._create_parser(bufnr, lang, opts)
language.require_language(lang)
if bufnr == 0 then
bufnr = a.nvim_get_current_buf()
end
vim.fn.bufload(bufnr)
local self = LanguageTree.new(bufnr, lang, opts)
---@private
local function bytes_cb(_, ...)
self:_on_bytes(...)
end
---@private
local function detach_cb(_, ...)
if parsers[bufnr] == self then
parsers[bufnr] = nil
end
self:_on_detach(...)
end
---@private
local function reload_cb(_, ...)
self:_on_reload(...)
end
a.nvim_buf_attach(
self:source(),
false,
{ on_bytes = bytes_cb, on_detach = detach_cb, on_reload = reload_cb, preview = true }
)
self:parse()
return self
end
--- Gets the parser for this bufnr / ft combination.
---
--- If needed this will create the parser.
--- Unconditionally attach the provided callback
---
---@param bufnr The buffer the parser should be tied to
---@param lang The filetype of this parser
---@param opts Options object to pass to the created language tree
---
---@returns The parser
function M.get_parser(bufnr, lang, opts)
opts = opts or {}
if bufnr == nil or bufnr == 0 then
bufnr = a.nvim_get_current_buf()
end
if lang == nil then
lang = a.nvim_buf_get_option(bufnr, 'filetype')
end
if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
parsers[bufnr] = M._create_parser(bufnr, lang, opts)
end
parsers[bufnr]:register_cbs(opts.buf_attach_cbs)
return parsers[bufnr]
end
--- Gets a string parser
---
---@param str The string to parse
---@param lang The language of this string
---@param opts Options to pass to the created language tree
function M.get_string_parser(str, lang, opts)
vim.validate({
str = { str, 'string' },
lang = { lang, 'string' },
})
language.require_language(lang)
return LanguageTree.new(str, lang, opts)
end
return M
|