:PROPERTIES: :ID: cc668372-8d95-461b-a7c6-3e2b51de3f40 :END: #+title: LSP #+filetags: emacs-load # SPDX-FileCopyrightText: 2022 Richard Brežák # # 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