From 2ffafc7aa91fb1d9a71fff12051e40961a7b7f69 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 9 May 2022 12:00:27 -0600 Subject: feat(lsp): add LspAttach and LspDetach autocommands The current approach of using `on_attach` callbacks for configuring buffers for LSP is suboptimal: 1. It does not use the standard Nvim interface for driving and hooking into events (i.e. autocommands) 2. There is no way for "third parties" (e.g. plugins) to hook into the event. This means that *all* buffer configuration must go into the user-supplied on_attach callback. This also makes it impossible for these configurations to be modular, since it all must happen in the same place. 3. There is currently no way to do something when a client detaches from a buffer (there is no `on_detach` callback). The solution is to use the traditional method of event handling in Nvim: autocommands. When a LSP client is attached to a buffer, fire a `LspAttach`. Likewise, when a client detaches from a buffer fire a `LspDetach` event. This enables plugins to easily add LSP-specific configuration to buffers as well as enabling users to make their own configurations more modular (e.g. by creating multiple LspAttach autocommands that each do something unique). --- test/functional/plugin/lsp_spec.lua | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'test/functional/plugin/lsp_spec.lua') diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 4cb7636825..6c961eff7d 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -18,6 +18,7 @@ local NIL = helpers.NIL local read_file = require('test.helpers').read_file local write_file = require('test.helpers').write_file local isCI = helpers.isCI +local meths = helpers.meths -- Use these to get access to a coroutine so that I can run async tests and use -- yield. @@ -341,6 +342,43 @@ describe('LSP', function() } end) + it('should fire autocommands on attach and detach', function() + local client + test_rpc_server { + test_name = "basic_init"; + on_setup = function() + exec_lua [[ + BUFFER = vim.api.nvim_create_buf(false, true) + vim.api.nvim_create_autocmd('LspAttach', { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + vim.g.lsp_attached = client.name + end, + }) + vim.api.nvim_create_autocmd('LspDetach', { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + vim.g.lsp_detached = client.name + end, + }) + ]] + end; + on_init = function(_client) + client = _client + eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)")) + client.notify('finish') + end; + on_handler = function(_, _, ctx) + if ctx.method == 'finish' then + eq('basic_init', meths.get_var('lsp_attached')) + exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)") + eq('basic_init', meths.get_var('lsp_detached')) + client.stop() + end + end; + } + end) + it('client should return settings via workspace/configuration handler', function() local expected_handlers = { {NIL, {}, {method="shutdown", client_id=1}}; -- cgit