diff --git a/docs/modules.org b/docs/modules.org index a0e7b9971..6f711a8a1 100644 --- a/docs/modules.org +++ b/docs/modules.org @@ -162,7 +162,7 @@ Small modules that give Emacs access to external tools & services. + gist - TODO + [[file:../modules/tools/lookup/README.org][lookup]] =+dictionary +docsets= - Universal jump-to & documentation lookup backend -+ [[file:../modules/tools/lsp/README.org][lsp]] - TODO ++ [[file:../modules/tools/lsp/README.org][lsp]] =+peek= - TODO + macos - TODO + magit - TODO + make - TODO diff --git a/modules/tools/lsp/README.org b/modules/tools/lsp/README.org index ab3f60a62..9cb4274c5 100644 --- a/modules/tools/lsp/README.org +++ b/modules/tools/lsp/README.org @@ -52,12 +52,11 @@ As of this writing, this is the state of LSP support in Doom Emacs: | [[../../lang/web/README.org][:lang web]] | web-mode, css-mode, scss-mode, sass-mode, less-css-mode | vscode-css-languageserver-bin, vscode-html-languageserver-bin | ** Module Flags -This module provides no flags. ++ =+peek= Enables the =lsp-ui-peek= navigation frontend provided by the =lsp-ui= package. ** Plugins + [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] + [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]] -+ [[https://github.com/tigersoldier/company-lsp][company-lsp]]* * Prerequisites This module has no direct prerequisites, but major-modes require you to install diff --git a/modules/tools/lsp/config.el b/modules/tools/lsp/config.el index a1df04f25..0b2e4f7da 100644 --- a/modules/tools/lsp/config.el +++ b/modules/tools/lsp/config.el @@ -1,11 +1,20 @@ ;;; tools/lsp/config.el -*- lexical-binding: t; -*- (defvar +lsp-company-backend 'company-lsp - "What backend to prepend to `company-backends' when `lsp-mode' is active. + "What backend to use for lsp-driven autocompletion, unless +overridden by `+lsp-capf-blacklist'. -This can be a single company backend or a list thereof. It can be anything -`company-backends' will accept.") +While `company-capf' does not require the `company-lsp' package +and should offer better performance, it has been integrated into +lsp only recently and as of 02/25/2020 is known to cause issues +with some language servers. If you wish to use `company-capf' in +general but fall back to `company-lsp' for specific language +servers, set `+lsp-company-backend' to `company-capf' and add the +excluded servers' identifiers to `+lsp-capf-blacklist'.") +(defvar +lsp-capf-blacklist '(ts-ls gopls) + "Language servers listed here will always use the `company-lsp' backend, +irrespective of what `+lsp-company-backend' is set to.") ;; ;;; Packages @@ -20,6 +29,42 @@ This can be a single company backend or a list thereof. It can be anything ;; Auto-kill LSP server once you've killed the last buffer associated with its ;; project. (setq lsp-keep-workspace-alive nil) + (add-hook! 'lsp-mode-hook + (defun +lsp-init-company-h () + (if (not (bound-and-true-p company-mode)) + (add-hook 'company-mode-hook #'+lsp-init-company-h t t) + (let ((preferred-backend +lsp-company-backend)) + (lsp-foreach-workspace + (when (memq (lsp--client-server-id (lsp--workspace-client lsp--cur-workspace)) + +lsp-capf-blacklist) + (setq preferred-backend 'company-lsp))) + (if (eq 'company-capf preferred-backend) + ;; use capf backend + (progn + (setq-local lsp-enable-completion-at-point t) + (setq-local lsp-prefer-capf t) + (setq-local company-backends + (cons 'company-capf (remq 'company-capf company-backends)))) + ;; use company-lsp backend (may need to be loaded first) + (require 'company-lsp) + (setq-local lsp-enable-completion-at-point nil) + (setq-local lsp-prefer-capf nil) + (setq-local company-backends + (cons 'company-lsp (remq 'company-capf company-backends))) + (setq-default company-lsp-cache-candidates 'auto)) + (remove-hook 'company-mode-hook #'+lsp-init-company-h t)))) + (defun +lsp-init-flycheck-or-flymake-h () + "Set up flycheck-mode or flymake-mode, depending on `lsp-diagnostic-package'." + (cond ((eq :none lsp-diagnostic-package)) + ((or (eq :flymake lsp-diagnostic-package) + (eq t lsp-diagnostic-package)) + (lsp--flymake-setup)) + ((require 'flycheck nil t) + (let ((old-checker flycheck-checker)) + (lsp-flycheck-enable t) + (when old-checker + (setq-local flycheck-checker old-checker) + (kill-local-variable 'flycheck-check-syntax-automatically))))))) ;; For `lsp-clients' (setq lsp-server-install-dir (concat doom-etc-dir "lsp/") @@ -79,7 +124,7 @@ modules. Also see: + `+lsp-init-company-h' (on `lsp-mode-hook') -+ `+lsp-init-ui-flycheck-or-flymake-h' (on `lsp-ui-mode-hook') ++ `+lsp-init-flycheck-or-flymake-h' (on `lsp-mode-hook') This also logs the resolved project root, if found, so we know where we are." :override #'lsp @@ -92,6 +137,10 @@ This also logs the resolved project root, if found, so we know where we are." (lsp--try-project-root-workspaces (equal arg '(4)) (and arg (not (equal arg 1)))))) + ;; read-process-output-max is only available on recent + ;; development builds of Emacs 27 and above + (when (boundp 'read-process-output-max) + (setq-local read-process-output-max (* 1024 1024))) (prog1 (lsp-mode 1) (setq-local lsp-buffer-uri (lsp--buffer-uri)) ;; Announce what project root we're using, for diagnostic purposes @@ -110,24 +159,9 @@ This also logs the resolved project root, if found, so we know where we are." (use-package! lsp-ui :hook (lsp-mode . lsp-ui-mode) - :init - (add-hook! 'lsp-ui-mode-hook - (defun +lsp-init-ui-flycheck-or-flymake-h () - "Sets up flymake-mode or flycheck-mode, depending on `lsp-prefer-flymake'." - (cond ((eq :none lsp-prefer-flymake)) - (lsp-prefer-flymake - (lsp--flymake-setup)) - ((require 'flycheck nil t) - (require 'lsp-ui-flycheck) - (let ((old-checker flycheck-checker)) - (lsp-ui-flycheck-enable t) - (when old-checker - (setq-local flycheck-checker old-checker) - (kill-local-variable 'flycheck-check-syntax-automatically))))))) :config - (setq lsp-prefer-flymake nil - lsp-ui-doc-max-height 8 + (setq lsp-ui-doc-max-height 8 lsp-ui-doc-max-width 35 lsp-ui-sideline-ignore-duplicate t ;; lsp-ui-doc is redundant with and more invasive than @@ -138,27 +172,10 @@ This also logs the resolved project root, if found, so we know where we are." ;; errors flash briefly and then disappear). lsp-ui-sideline-show-hover nil) - (set-lookup-handlers! 'lsp-ui-mode :async t - :definition 'lsp-ui-peek-find-definitions - :references 'lsp-ui-peek-find-references)) - - -(use-package! company-lsp - :when (featurep! :completion company) - :defer t - :init - ;; Make sure that `company-capf' is disabled since it is incompatible with - ;; `company-lsp' (see lsp-mode#884) - (add-hook! 'lsp-mode-hook - (defun +lsp-init-company-h () - (if (not (bound-and-true-p company-mode)) - (add-hook 'company-mode-hook #'+lsp-init-company-h t t) - (setq-local company-backends - (cons +lsp-company-backend - (remq 'company-capf company-backends))) - (remove-hook 'company-mode-hook #'+lsp-init-company-h t)))) - :config - (setq company-lsp-cache-candidates 'auto)) ;; cache candidates for better performance + (when (featurep! +peek) + (set-lookup-handlers! 'lsp-ui-mode :async t + :definition 'lsp-ui-peek-find-definitions + :references 'lsp-ui-peek-find-references))) (use-package! helm-lsp diff --git a/modules/tools/lsp/packages.el b/modules/tools/lsp/packages.el index e2f449548..01f263ace 100644 --- a/modules/tools/lsp/packages.el +++ b/modules/tools/lsp/packages.el @@ -1,8 +1,8 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/lsp/packages.el -(package! lsp-mode :pin "2fc0963a50") -(package! lsp-ui :pin "e8200e3b72") +(package! lsp-mode :pin "fc812bea1f") +(package! lsp-ui :pin "da9788b427") (when (featurep! :completion company) (package! company-lsp :pin "f921ffa0cd")) (when (featurep! :completion ivy)