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
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
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)))