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
|
local servers = require "nvim-lsp-installer.servers"
local functional = require "nvim-lsp-installer.core.functional"
local log = require "nvim-lsp-installer.log"
local filter, compose = functional.filter, functional.compose
---@class LspInfoClient
---@field name string
---@field cmd string[]
---@field cmd_diagnostics {lineno: integer}|nil
---@param client LspInfoClient
local function is_client_managed(client)
local ok, server = servers.get_server(client.name)
return ok and server:is_installed()
end
---@param client LspInfoClient
local function client_has_cmd_diagnostics(client)
return client.cmd_diagnostics ~= nil
end
---@param client LspInfoClient
local function client_has_cmd(client)
return client.cmd ~= nil
end
---@param client LspInfoClient[]
local function is_cmd_executable(client)
local cmd = client.cmd[1]
local ok, server = servers.get_server(client.name)
if not ok then
-- should not really happen
return false
end
local options = server:get_default_options()
local path = options.cmd_env and options.cmd_env.PATH
if path then
local old_path = vim.env.PATH
local is_executable = pcall(function()
vim.env.PATH = path
assert(vim.fn.executable(cmd) == 1)
end)
vim.env.PATH = old_path
return is_executable
else
return vim.fn.executable(cmd) == 1
end
end
local ok, err = pcall(function()
---@type LspInfoClient[]
local clients = {}
local lines = vim.api.nvim_buf_get_lines(0, 1, -1, false)
local function parse_line(line)
local client_name = line:match "^%s+Client:%s+(.+)%s+%(.*$"
if client_name then
return "client_header", client_name
end
local config_name = line:match "^%s+Config:%s+(.+)$"
if config_name then
return "client_header", config_name
end
local cmd_diagnostics = line:match "^%s+cmd is executable:.*$"
if cmd_diagnostics then
return "cmd_diagnostics"
end
local cmd = line:match "^%s+cmd:%s+(.+)$"
if cmd then
return "cmd", vim.split(cmd, "%s")
end
end
local current_client
for lineno, line in ipairs(lines) do
local type, value = parse_line(line)
if type == "client_header" then
current_client = { name = value }
table.insert(clients, current_client)
elseif type == "cmd_diagnostics" then
current_client.cmd_diagnostics = { lineno = lineno }
elseif type == "cmd" then
current_client.cmd = value
end
end
---@type LspInfoClient[]
local executable_clients = compose(
filter(is_cmd_executable),
filter(client_has_cmd),
filter(client_has_cmd_diagnostics),
filter(is_client_managed)
)(clients)
local override_cmd_diagnostics = functional.partial(functional.each, function(client)
vim.api.nvim_buf_set_lines(
0,
client.cmd_diagnostics.lineno,
client.cmd_diagnostics.lineno + 1,
false,
{ " cmd is executable: true (checked by nvim-lsp-installer)" }
)
end)
vim.api.nvim_buf_set_option(0, "modifiable", true)
override_cmd_diagnostics(executable_clients)
vim.api.nvim_buf_set_option(0, "modifiable", false)
end)
if not ok then
log.error("Failed to patch :LspInfo window", err)
end
|