ex_cmd.lua (5437B)
1 local api = vim.api 2 local lsp = vim.lsp 3 4 local M = {} 5 6 --- @param msg string 7 local function echo_err(msg) 8 api.nvim_echo({ { msg } }, true, { err = true }) 9 end 10 11 --- @return string[] 12 local function get_client_names() 13 return vim 14 .iter(lsp.get_clients()) 15 :map(function(client) 16 return client.name 17 end) 18 :unique() 19 :totable() 20 end 21 22 --- @return string[] 23 local function get_config_names() 24 local config_names = vim 25 .iter(api.nvim_get_runtime_file('lsp/*.lua', true)) 26 --- @param path string 27 :map(function(path) 28 local file_name = path:match('[^/]*.lua$') 29 return file_name:sub(0, #file_name - 4) 30 end) 31 :totable() 32 33 --- @diagnostic disable-next-line 34 vim.list_extend(config_names, vim.tbl_keys(lsp.config._configs)) 35 36 return vim 37 .iter(config_names) 38 :unique() 39 --- @param name string 40 :filter(function(name) 41 return name ~= '*' 42 end) 43 :totable() 44 end 45 46 --- @param filter fun(string):boolean 47 --- @return fun():string[] 48 local function filtered_config_names(filter) 49 return function() 50 return vim.iter(get_config_names()):filter(filter):totable() 51 end 52 end 53 54 local complete_args = { 55 enable = filtered_config_names(function(name) 56 return not lsp.is_enabled(name) 57 end), 58 disable = filtered_config_names(function(name) 59 return lsp.is_enabled(name) 60 end), 61 restart = get_client_names, 62 stop = get_client_names, 63 } 64 65 --- @param names string[] 66 --- @param enable? boolean 67 local function checked_enable(names, enable) 68 for _, name in ipairs(names) do 69 if name:find('*') == nil and lsp.config[name] ~= nil then 70 lsp.enable(name, enable) 71 else 72 echo_err(("No client config named '%s'"):format(name)) 73 end 74 end 75 end 76 77 --- @param config_names string[] 78 local function ex_lsp_enable(config_names) 79 -- Default to enabling all clients matching the filetype of the current buffer. 80 if #config_names == 0 then 81 local filetype = vim.bo.filetype 82 for _, name in ipairs(get_config_names()) do 83 local success, result = pcall(function() 84 return lsp.config[name] 85 end) 86 if success then 87 local filetypes = result.filetypes 88 if filetypes == nil or vim.list_contains(filetypes, filetype) then 89 table.insert(config_names, name) 90 end 91 else 92 echo_err(result --[[@as string]]) 93 end 94 end 95 if #config_names == 0 then 96 if filetype == '' then 97 echo_err('Current buffer has no filetype') 98 else 99 echo_err(("No configs for filetype '%s'"):format(filetype)) 100 end 101 return 102 end 103 end 104 105 checked_enable(config_names) 106 end 107 108 --- @param config_names string[] 109 local function ex_lsp_disable(config_names) 110 -- Default to disabling all clients attached to the current buffer. 111 if #config_names == 0 then 112 config_names = vim 113 .iter(lsp.get_clients { bufnr = api.nvim_get_current_buf() }) 114 :map(function(client) 115 return client.name 116 end) 117 :filter(function(name) 118 return lsp.config[name] ~= nil 119 end) 120 :totable() 121 if #config_names == 0 then 122 echo_err('No configs with clients attached to current buffer') 123 return 124 end 125 end 126 127 checked_enable(config_names, false) 128 end 129 130 --- @param client_names string[] 131 --- @return vim.lsp.Client[] 132 local function get_clients_from_names(client_names) 133 -- Default to all active clients attached to the current buffer. 134 if #client_names == 0 then 135 local clients = lsp.get_clients { bufnr = api.nvim_get_current_buf() } 136 if #clients == 0 then 137 echo_err('No clients attached to current buffer') 138 end 139 return clients 140 else 141 return vim 142 .iter(client_names) 143 :map(function(name) 144 local clients = lsp.get_clients { name = name } 145 if #clients == 0 then 146 echo_err(("No active clients named '%s'"):format(name)) 147 end 148 return clients 149 end) 150 :flatten() 151 :totable() 152 end 153 end 154 155 --- @param client_names string[] 156 local function ex_lsp_restart(client_names) 157 local clients = get_clients_from_names(client_names) 158 159 for _, client in ipairs(clients) do 160 client:_restart(client.exit_timeout) 161 end 162 end 163 164 --- @param client_names string[] 165 local function ex_lsp_stop(client_names) 166 local clients = get_clients_from_names(client_names) 167 168 for _, client in ipairs(clients) do 169 client:stop(client.exit_timeout) 170 end 171 end 172 173 local actions = { 174 enable = ex_lsp_enable, 175 disable = ex_lsp_disable, 176 restart = ex_lsp_restart, 177 stop = ex_lsp_stop, 178 } 179 180 local available_subcmds = vim.tbl_keys(actions) 181 182 --- Implements command: `:lsp {subcmd} {name}?`. 183 --- @param args string 184 M.ex_lsp = function(args) 185 local fargs = api.nvim_parse_cmd('lsp ' .. args, {}).args 186 if not fargs then 187 return 188 end 189 local subcmd = fargs[1] 190 if not vim.list_contains(available_subcmds, subcmd) then 191 echo_err(("Invalid subcommand '%s'"):format(subcmd)) 192 return 193 end 194 195 local clients = { unpack(fargs, 2) } 196 197 actions[subcmd](clients) 198 end 199 200 --- Completion logic for `:lsp` command 201 --- @param line string content of the current command line 202 --- @return string[] list of completions 203 function M.lsp_complete(line) 204 local split = vim.split(line, '%s+') 205 if #split == 2 then 206 return available_subcmds 207 else 208 local subcmd = split[2] 209 return vim 210 .iter(complete_args[subcmd]()) 211 --- @param n string 212 :map(function(n) 213 return vim.fn.escape(n, ' \t') 214 end) 215 :totable() 216 end 217 end 218 219 return M