Emacs LSP
20 Jan 2023 • Leave CommentsLSP
Language Server Protocol (LSP) is originally from Mircosoft and now develops to a standard protocol.
LSP works in a client/server mode. In this post, the client is usually package of IDE (e.g. Emacs), while the server is specific to programing language (e.g. C/C++).
To configure Emacs with LSP support, we firstly, install the eglot in Emacs, then install a language-specific LSP server on your host, and might do some setup in init.el depending on the LSP server requirement.
Emacs eglot
Emacs supports LSP by its built-in package eglot or 3rd-party package lsp-mode.
eglot has less features but requires less dependencies. What is more, it is official!
- To install the eglot client, just run
M-x package-install RET eglot RET
. - To start eglot for a LSP.
- Manually run
M-x eglot
. - Automatically by
(add-hook 'foo-mode-hook 'eglot-ensure)
.
- Manually run
- To turn off eglot and LSP.
- Manually run
M-x eglot-shutdown
. - Automatically by
(setq eglot-autoshutdown t)
.
- Manually run
LSP Servers
C/C++ clangd
Install the C/C++ LSP server clangd on Arch Linux.
~ $ sudo pacman -S clang
~ $ clangd --version
Make sure the value of variable eglot-server-programs contains c-mode
and c++-mode
. All the languages major mode listed here in is enabed by default.
Please open up a C/C++ source file and run M-x eglot
. You will find LSP server clangd is automatically launched on your host, as the child process of Emacs. To shutdown the LSP server, just run M-x eglot-shutdown
.
However, we'd like to automatically launch the LSP server upon a C/C++ source file is loaded. Add the following contents init.el.
(require 'eglot)
(add-hook 'c-mode-hook 'eglot-ensure)
(add-hook 'c++-mode-hook 'eglot-ensure)
lua-lsp
deprecated; see lua-language-server
This section assumes we are in Arch Linux system with mutliple Lua versions installed (e.g. extra/lua53 and extra/lua54).
To install lua-lsp, we should install Lua package manager luarocks first.
~ $ sudo pacman -S luarocks
Default Luarocks config (just a Lua script) is located under /etc/luarocks. We can inspect the full configuration of Lua 5.3
as below.
~ $ luarocks --lua-version 5.3 config --scope user
config_files = {
nearest = "/etc/luarocks/config-5.3.lua",
system = {
file = "/etc/luarocks/config-5.3.lua",
found = true
},
user = {
file = "/home/outsinre/.luarocks/config-5.3.lua",
found = true
}
}
--
-- skipped
--
rocks_trees = {
{
name = "user",
root = "/home/outsinre/.luarocks"
},
{
name = "system",
root = "/usr"
}
}
rocks_trees
refers the the root dir storing rocks contents. To avoid conflicts, we'd better configure different rocks tree for different Lua versions. Take Lua 5.3
for example, we will configure its rocks tree to ~/.luarocks53.
Let's change the current user's rocks tree for Lua 5.3
.
~$ mkdir -p $HOME/.config/luarocks/
~$ cp /etc/luarocks/config-5.3.lua .config/luarocks/
~ $ vim .config/luarocks/config-5.3.lua
>{ name = "user", root = home .. "/.luarocks53" };
~ $ luarocks --lua-version 5.3 config --scope user
Finally, we install lua-lsp by explicitly provide the rocks tree.
# please omit option '--local'
~ $ luarocks --lua-version 5.3 --tree ~/.luarocks53 --server=http://luarocks.org/dev install lua-lsp
Now, we add the lua-lsp binary to PATH.
# ~/.bash_profile
eval $(luarocks --lua-version 5.3 path)
The built-in method above is provided by Luarocks but it exports LUA_PATH
and LUA_CPATH
as well. We may just want to set "PATH".
~ $ nano -w ~/.bash_profile
>PATH=$HOME/.luarocks53/bin:$PATH
To automatically launch lua-lsp, add the following lines to init.el.
(require 'eglot)
(add-hook 'lua-mode-hook 'eglot-ensure)
Repeat above steps for other Lua versions.
lua-language-server
lua-lsp has not been updated for years, and so we swtich the lua-language-server.
Let's install "lua-language-server" manually per-user.
~ $ wget https://github.com/LuaLS/lua-language-server/releases/download/3.6.19/lua-language-server-3.6.19-linux-x64.tar.gz
~ $ mkdir -p ~/.local/share/lua-language-server
~ $ tar -xzvf lua-language-server-3.6.19-linux-x64.tar.gz -C ~/.local/share/lua-language-server
We cannot add lua-language-server to "PATH" directly, instead we must create a wrapper, namely ~/bin/lsp-lua.
#!/usr/bin/env bash
exec "${HOME}/.local/share/lua-language-server/bin/lua-language-server" "--configpath=${HOME}/.local/share/lua-language-server/settings.lua" "$@"
Now let's have a try.
~ $ lsp-lua --version
3.6.19
lua-language-server by default is not added to eglot. So, we should manually set it up in init.el.
(add-to-list 'eglot-server-programs
'(lua-mode "~/bin/lsp-lua"))
(add-hook 'lua-mode-hook 'eglot-ensure)
Restart Emacs and open a Lua file, eglot would automatically invokes ~/bi/lsp-lua to launch lua-language-server.
Before closing this section, let's configure lua-language-server a bit. Remember that, ~/bin/lsp-lua has specified the option --configpath
to configurations from a Lua file settings.lua as follows. Plese read Settings for a complete list of parameters.
return {
Lua = {
["runtime.version"] = "Lua 5.1",
completion = {
callSnippet = "Both",
displayContext = 1,
keywordSnippet = "Both",
},
["hint.enable"] = true,
["format.enable"] = true,
}
}
To format current buffer, just run M-x: eglot-format-buffer
.