aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/treesitter/language.lua
blob: 47abf653328e0f9ddc8e56d99047ec60ba47096f (plain) (blame)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
local api = vim.api

local M = {}

---@type table<string,string>
local ft_to_lang = {
  help = 'vimdoc',
}

--- Get the filetypes associated with the parser named {lang}.
--- @param lang string Name of parser
--- @return string[] filetypes
function M.get_filetypes(lang)
  local r = {} ---@type string[]
  for ft, p in pairs(ft_to_lang) do
    if p == lang then
      r[#r + 1] = ft
    end
  end
  return r
end

--- @param filetype string
--- @return string|nil
function M.get_lang(filetype)
  if filetype == '' then
    return
  end
  if ft_to_lang[filetype] then
    return ft_to_lang[filetype]
  end
  -- support subfiletypes like html.glimmer
  filetype = vim.split(filetype, '.', { plain = true })[1]
  return ft_to_lang[filetype]
end

---@deprecated
function M.require_language(lang, path, silent, symbol_name)
  vim.deprecate(
    'vim.treesitter.language.require_language()',
    'vim.treesitter.language.add()',
    '0.12'
  )
  local opts = {
    silent = silent,
    path = path,
    symbol_name = symbol_name,
  }

  if silent then
    local installed = pcall(M.add, lang, opts)
    return installed
  end

  M.add(lang, opts)
  return true
end

---@class vim.treesitter.language.add.Opts
---@inlinedoc
---
---Default filetype the parser should be associated with.
---(Default: {lang})
---@field filetype? string|string[]
---
---Optional path the parser is located at
---@field path? string
---
---Internal symbol name for the language to load
---@field symbol_name? string

--- Load parser with name {lang}
---
--- Parsers are searched in the `parser` runtime directory, or the provided {path}
---
---@param lang string Name of the parser (alphanumerical and `_` only)
---@param opts? vim.treesitter.language.add.Opts Options:
function M.add(lang, opts)
  opts = opts or {}
  local path = opts.path
  local filetype = opts.filetype or lang
  local symbol_name = opts.symbol_name

  vim.validate({
    lang = { lang, 'string' },
    path = { path, 'string', true },
    symbol_name = { symbol_name, 'string', true },
    filetype = { filetype, { 'string', 'table' }, true },
  })

  if vim._ts_has_language(lang) then
    M.register(lang, filetype)
    return
  end

  if path == nil then
    if not (lang and lang:match('[%w_]+') == lang) then
      error("'" .. lang .. "' is not a valid language name")
    end

    local fname = 'parser/' .. lang .. '.*'
    local paths = api.nvim_get_runtime_file(fname, false)
    if #paths == 0 then
      error("no parser for '" .. lang .. "' language, see :help treesitter-parsers")
    end
    path = paths[1]
  end

  vim._ts_add_language(path, lang, symbol_name)
  M.register(lang, filetype)
end

--- @param x string|string[]
--- @return string[]
local function ensure_list(x)
  if type(x) == 'table' then
    return x
  end
  return { x }
end

--- Register a parser named {lang} to be used for {filetype}(s).
---
--- Note: this adds or overrides the mapping for {filetype}, any existing mappings from other
--- filetypes to {lang} will be preserved.
---
--- @param lang string Name of parser
--- @param filetype string|string[] Filetype(s) to associate with lang
function M.register(lang, filetype)
  vim.validate({
    lang = { lang, 'string' },
    filetype = { filetype, { 'string', 'table' } },
  })

  for _, f in ipairs(ensure_list(filetype)) do
    if f ~= '' then
      ft_to_lang[f] = lang
    end
  end
end

--- Inspects the provided language.
---
--- Inspecting provides some useful information on the language like node names, ...
---
---@param lang string Language
---@return table
function M.inspect(lang)
  M.add(lang)
  return vim._ts_inspect_language(lang)
end

return M