dotfiles/emacs-lisp/lsp.org
magic_rb 941df7e990
emacs: LSP doesn't clean up its own mess
Signed-off-by: magic_rb <magic_rb@redalder.org>
2024-11-09 22:15:03 +01:00

166 lines
5 KiB
Org Mode

:PROPERTIES:
:ID: cc668372-8d95-461b-a7c6-3e2b51de3f40
:END:
#+title: LSP
#+filetags: emacs-load
# SPDX-FileCopyrightText: 2022 Richard Brežák <richard@brezak.sk>
#
# SPDX-License-Identifier: LGPL-3.0-or-later
Disable server downloading suggestions, and other features.
#+begin_src emacs-lisp
(setq lsp-enable-suggest-server-download nil
lsp-enable-snippet nil
lsp-enable-dap-auto-configure nil
lsp-enable-on-type-formatting nil)
#+end_src
Sometimes LSP mode failes to clean up after itself, so clean up its mess.
#+begin_src emacs-lisp
(defun vherrmann/cleanup-lsp-mode-post-command-hook()
"Cleans up lsp-modes mess."
(when (bound-and-true-p lsp-mode)
(setq-default post-command-hook
(--filter (not (and (consp it)
(eq (car it) 'closure)
(not (-difference
'(cancel-callback method buf hook workspaces id)
(-map #'car (cadr it))))))
(default-value 'post-command-hook)))))
(add-hook 'kill-buffer-hook #'vherrmann/cleanup-lsp-mode-post-command-hook)
#+end_src
* Python
Using the Microsoft language server as it's the best afaik. It's weird because it doesn't lookup the path to itself via PATH but has to be statically set.
#+BEGIN_SRC emacs-lisp
(defun magic_rb/locate-python-executable-lsp-deffered ()
"Locates the python executable available to the current buffer and only then calls `lsp-deferred'."
(lambda ()
(require 'lsp-python-ms)
(envrc-mode)
(setq-local lsp-python-ms-executable (executable-find "python-language-server"))
(lsp-deferred)))
(use-package lsp-python-ms
:straight t
:after (lsp-mode)
:hook (python-mode . magic_rb/locate-python-executable-lsp-deffered)
:config
(defvar-local lsp-python-ms-executable ""))
#+END_SRC
* C/C++
This just requires hooking lsp onto ~c-mode~ and ~c++-mode~.
#+BEGIN_SRC emacs-lisp
(use-package lsp-c++-c
:after (lsp-mode)
:no-require t
:init
(add-hook 'c-mode-hook #'lsp-deferred)
(add-hook 'c++-mode-hook #'lsp-deferred))
#+END_SRC
#+RESULTS:
: t
* Haskell
Enable ~haskell-mode~, and ~lsp-haskell~
#+BEGIN_SRC emacs-lisp
(use-package haskell-mode
:straight t
:hook
(((haskell-mode haskell-literate-mode) . interactive-haskell-mode)
((heskell-mode haskell-literate-mode) . haskell-indentation-mode))
:config
(setq lsp-haskell-plugin-ghcide-type-lenses-global-on nil
lsp-haskell-plugin-import-lens-code-lens-on nil))
(use-package lsp-haskell
:straight t
:after (haskell-mode lsp-mode)
:hook ((haskell-mode haskell-literate-mode) . lsp-deferred))
#+END_SRC
Disable the ~haskell-stack-ghc~ flycheck checker, it's not used when lsp starts, but it does get loaded just before it. Loading and unloading it is slow and causes Emacs to freeze for a few seconds, so just disable it.
#+BEGIN_SRC emacs-lisp
(with-eval-after-load "flycheck"
(add-to-list 'flycheck-disabled-checkers 'haskell-stack-ghc))
#+END_SRC
* Javascript
Enable ~rjsx-mode~ instead of ~javascript-mode~ or ~js2-mode~ as it properly handles inline HTML.
#+BEGIN_SRC emacs-lisp
(use-package rjsx-mode
:straight t
:config
:mode ("\\.js\\'" . rjsx-mode)
:mode ("\\.jsx\\'" . rjsx-mode)
:hook (rjsx-mode . lsp-deferred)
:init
;; Originally this function exits with a call to `error`, which causes the simple "PATH lookup"
;; scheme to not be tried
(cl-defun lsp--npm-dependency-path (&key package path &allow-other-keys)
"Return npm dependency PATH for PACKAGE."
(let ((path (executable-find
(f-join lsp-server-install-dir "npm" package
(cond ((eq system-type 'windows-nt) "")
(t "bin"))
path))))
(unless (and path (f-exists? path))
nil)
path)))
#+END_SRC
* Typescript
Enable ~typescript-mode~ for =.ts=, =.tsx= and hook ~lsp-mode~ on it. It doesn't specifically support inline HTML,
but aside from minor indentation issues it works fine.
#+BEGIN_SRC emacs-lisp
(use-package typescript-mode
:straight t
:config
:mode ("\\.ts\\'" . typescript-mode)
:mode ("\\.tsx\\'" . typescript-mode)
:hook (typescript-mode . lsp-deferred))
#+END_SRC
* HTML Markup Language
Enable ~web-mode~ for =.html=, =.xhtml= and hook ~lsp-mode~ on it.
#+BEGIN_SRC emacs-lisp
(use-package web-mode
:straight t
:mode ("\\.html\\'" . web-mode)
:mode ("\\.xhtml\\'" . web-mode)
:hook (web-mode . lsp-deferred))
#+END_SRC
* CSS Style Sheet Language
Enable ~css-mode~ for =.css=, =.scss= and hook ~lsp-mode~ on it. Also make ~flycheck~ happy.
#+BEGIN_SRC emacs-lisp
(use-package css-mode
:mode ("\\.css\\'" . css-mode)
:mode ("\\.scss\\'". css-mode)
:hook (css-mode . lsp-deferred)
:config
(with-eval-after-load "flycheck"
(flycheck-add-mode 'javascript-eslint 'web-mode)))
#+END_SRC