The Complete Computing Environment

Emacs and the Language Server Protocol

(provide 'cce/lsp-base)

Language Server Protocol is a semi-standard protocol for IDEs and tools to be able to reason about code without having to implement direct support for that language. The complexity of language integration is handled in a server (usually written in the same language) which exposes smart information and functionality to work with the code.

What this means for me is that there is always a basic amount of support that can be implied – there are packages which integrate Emacs better with a language than LSP, perhaps, but that is also perhaps not necessary. I work through programming philosophy of arbitrary languages in their own pages, and focus here instead on configuring lsp-mode and company-mode

company-lsp is deprecated

(use-package lsp-mode
  (setq lsp-file-watch-threshold nil)
  (add-to-list 'company-backends 'company-capf))
(use-package lsp-ui
  (setq lsp-ui-doc-enable nil))

With lsp-mode installed, language support pages can just add lsp-mode to their programming language's mode-hook to enable it. It'll try to connect to the language server or start one, and then present functionality. I present that functionality to myself with hydra-lsp:

(defhydra hydra-lsp (:exit t :hint nil)
 Buffer^^               Server^^                   Symbol
 [_f_] format           [_M-r_] restart            [_d_] declaration  [_i_] implementation  [_o_] documentation
 [_m_] imenu            [_S_]   shutdown           [_D_] definition   [_t_] type            [_r_] rename
 [_x_] execute action   [_M-s_] describe session   [_R_] references   [_s_] signature       [_e_] flycheck"
  ("d" lsp-find-declaration)
  ("D" lsp-ui-peek-find-definitions)
  ("R" lsp-ui-peek-find-references)
  ("i" lsp-ui-peek-find-implementation)
  ("t" lsp-find-type-definition)
  ("s" lsp-signature-help)
  ("o" lsp-describe-thing-at-point)
  ("r" lsp-rename)
  ("e" lsp-ui-flycheck-list)

  ("f" lsp-format-buffer)
  ("m" lsp-ui-imenu)
  ("x" lsp-execute-code-action)

  ("M-s" lsp-describe-session)
  ("M-r" lsp-restart-workspace)
  ("S" lsp-shutdown-workspace))

(add-hook 'lsp-mode-hook (lambda ()
                            (evil-local-set-key 'normal (kbd "<SPC>l") #'hydra-lsp/body)))

and so in languages which support lsp-mode, I can hit <SPC>ld to jump to the declaration of a the function my point is underneath. useful stuff.