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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
-- Here be dragons
local Ui = require "nvim-lsp-installer.ui"
local Data = require "nvim-lsp-installer.data"
local list_map = Data.list_map
local property_type_highlights = {
["string"] = "String",
["string[]"] = "String",
["boolean"] = "Boolean",
["number"] = "Number",
["integer"] = "Number",
}
local function resolve_type(property_schema)
if vim.tbl_islist(property_schema.type) then
return table.concat(property_schema.type, " | ")
elseif property_schema.type == "array" then
if property_schema.items then
return ("%s[]"):format(property_schema.items.type)
else
return property_schema.type
end
end
return property_schema.type or "N/A"
end
local function Indent(indentation, children)
-- create a list table with as many "INDENT" entries as the numeric indentation variable
local indent = {}
for _ = 1, indentation do
table.insert(indent, "INDENT")
end
return Ui.CascadingStyleNode(indent, children)
end
---@param server ServerState
---@param schema table
---@param key string|nil
---@param level number
---@param key_width number @The width the key should occupate in the UI to produce an even column.
---@param compound_key string|nil
local function ServerSettingsSchema(server, schema, key, level, key_width, compound_key)
level = level or 0
compound_key = ("%s%s"):format(compound_key or "", key or "")
local toggle_expand_keybind = Ui.Keybind(
"<CR>",
"TOGGLE_SERVER_SCHEMA_SETTING",
{ name = server.name, key = compound_key }
)
local node_is_expanded = server.expanded_schema_properties[compound_key]
local key_prefix = node_is_expanded and "↓ " or "→ "
if (schema.type == "object" or schema.type == nil) and schema.properties then
local nodes = {}
if key then
-- This node belongs to some parent object - render a heading for it.
-- It'll act as the anchor for its children.
local heading = Ui.HlTextNode {
key_prefix .. key,
node_is_expanded and "LspInstallerLabel" or "",
}
nodes[#nodes + 1] = heading
nodes[#nodes + 1] = toggle_expand_keybind
end
-- All level 0 nodes are expanded by default - otherwise we'd not render anything at all
if level == 0 or node_is_expanded then
local max_property_length = 0
local sorted_properties = {}
for property in pairs(schema.properties) do
max_property_length = math.max(max_property_length, vim.api.nvim_strwidth(property))
sorted_properties[#sorted_properties + 1] = property
end
-- TODO sort at moment of insert?
table.sort(sorted_properties)
for _, property in ipairs(sorted_properties) do
nodes[#nodes + 1] = Indent(level, {
ServerSettingsSchema(
server,
schema.properties[property],
property,
level + 1,
max_property_length,
compound_key
),
})
end
end
return Ui.Node(nodes)
elseif schema.oneOf then
local nodes = {}
for i, alternative_schema in ipairs(schema.oneOf) do
nodes[#nodes + 1] = ServerSettingsSchema(
server,
alternative_schema,
("%s (alt. %d)"):format(key, i),
level,
key_width,
compound_key
)
end
return Ui.Node(nodes)
else
-- Leaf node (aka any type that isn't an object)
local type = resolve_type(schema)
local heading
local label = (key_prefix .. key .. (" "):rep(key_width)):sub(1, key_width + 5) -- + 5 to account for key_prefix plus some extra whitespace
if schema.default ~= nil then
heading = Ui.HlTextNode {
{
{
label,
node_is_expanded and "LspInstallerLabel" or "",
},
{
" default: ",
"Comment",
},
{
vim.json.encode(schema.default),
property_type_highlights[type] or "LspInstallerMuted",
},
},
}
else
heading = Ui.HlTextNode {
label,
node_is_expanded and "LspInstallerLabel" or "",
}
end
return Ui.Node {
heading,
toggle_expand_keybind,
Ui.When(node_is_expanded, function()
local description = list_map(function(line)
return { { line, "Comment" } }
end, vim.split(schema.description or "No description available.", "\n"))
local type_highlight = property_type_highlights[type] or "LspInstallerMuted"
local table_rows = {
{ { "type", "LspInstallerMuted" }, { type, type_highlight } },
}
if vim.tbl_islist(schema.enum) then
for idx, enum in ipairs(schema.enum) do
local enum_description = ""
if schema.enumDescriptions and schema.enumDescriptions[idx] then
enum_description = "- " .. schema.enumDescriptions[idx]
end
table_rows[#table_rows + 1] = {
{ idx == 1 and "possible values" or "", "LspInstallerMuted" },
{ vim.json.encode(enum), type_highlight },
{ enum_description, "Comment" },
}
end
end
return Indent(level, {
Ui.HlTextNode(description),
Ui.Table(table_rows),
})
end),
}
end
end
return ServerSettingsSchema
|