Language Servers in Emacs¶
I use eglot
as my language client since it is available out of the box and integrates nicely with core packages like xref
emacs/init.el
(use-package eglot
:bind (("<f2>" . eglot-rename))
:custom
(eglot-autoshutdown t)
(eglot-extend-to-xref t)
:config
(advice-add 'eglot--workspace-configuration-plist :around #'alc-eglot-fix-workspace-configuration-scope)
(add-to-list 'display-buffer-alist
'("\\*EGLOT workspace configuration\\*"
(display-buffer-below-selected)
(dedicated . t))))
Workspace Configuration¶
Convincing eglot
to apply the correct workspace/configuration
settings for the current server and project is the single most frustrating part of using it…
One issue is making sure eglot
evaluates settings at the right scope
emacs/init.el
(require 's)
(defun alc-eglot-fix-workspace-configuration-scope (orig-fun server &optional path)
"Fix the scopeUri of a workspace/configuration request.
When eglot handles a workspace/configuration request with an
associated scopeUri it uses the `file-name-directory' function to
determine the directory from which to resolve the configuration
values.
This causes an issue for servers like esbonio and pyright which
set the scopeUri to a directory. For `file-name-directory' to
treat the path as a directory it must include a trailing slash, a
convention which these servers do not follow.
Therefore `file-name-directory' treats the path as a file and
removes the final component, causing eglot to resolve the
configuration relative to the wrong directory.
This function fixes the issue by advising the
`eglot--workspace-configuration-plist' function, ensuring that
paths referencing directories include the trailing slash."
(if (and path
(file-directory-p path)
(not (s-ends-with? "/" path)))
(funcall orig-fun server (concat path "/"))
(funcall orig-fun server path)))