diff --git a/layers/+tools/lsp/README.org b/layers/+tools/lsp/README.org new file mode 100644 index 000000000..649c49978 --- /dev/null +++ b/layers/+tools/lsp/README.org @@ -0,0 +1,33 @@ +#+TITLE: LSP layer + +* Table of Contents :TOC_4_gh:noexport: +- [[#description][Description]] + - [[#features][Features:]] +- [[#configuration][Configuration]] + +* Description +This layer adds support for basic language server protocol packages speaking [[https://microsoft.github.io/language-server-protocol/specification][language server protocol]]. + +** Features: +- Cross references (definitions, references, document symbol, workspace symbol search and others) +- Workspace-wide symbol rename +- Symbol highlighting +- Flycheck +- Completion with =company-lsp= +- Signature help with eldoc +- Symbol documentation in a child frame (=lsp-ui-doc=) + +Each language server may support the language server protocol in varying degree and they may also provide extensions, check the language server's website for details. +=M-x lsp-capabilities= in a LSP buffer to list capabilities of the server. + +* Configuration +The LSP ecosystem is based on two packages: [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] and [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]]. +Please check out their documentation. + +If you add =lsp-*-enable= to major mode hooks for auto initialization of language clients, customize =lsp-project-whitelist= =lsp-project-blacklist= to disable projects you don't want to enable LSP. + +If some features doe not work as intended, here is a common check list. + +- =M-x lsp-capabilities= If the LSP workspace is initialized correctly +- =M-: xref-backend-functions= should be =(lsp--xref-backend)= for cross references +- =M-: completion-at-point-functions= should be =(lsp-completion-at-point)= for completion diff --git a/layers/+tools/lsp/funcs.el b/layers/+tools/lsp/funcs.el new file mode 100644 index 000000000..d6f20739c --- /dev/null +++ b/layers/+tools/lsp/funcs.el @@ -0,0 +1,19 @@ +(defun lsp//sync-peek-face () + "Synchronize the face used in lsp-ui peek window according to the theme." + (set-face-attribute 'lsp-ui-peek-list nil + :background (face-attribute 'hl-line :background nil t)) + (set-face-attribute 'lsp-ui-peek-peek nil + :background (face-attribute 'hl-line :background nil t)) + (set-face-attribute 'lsp-ui-peek-selection nil + :background (face-attribute 'highlight :background nil t) + :foreground (face-attribute 'default :foreground nil t)) + (set-face-attribute 'lsp-ui-peek-filename nil + :foreground (face-attribute 'font-lock-constant-face :foreground nil t)) + (set-face-attribute 'lsp-ui-peek-highlight nil + :background (face-attribute 'highlight :background nil t) + :foreground (face-attribute 'highlight :foreground nil t) + :distant-foreground (face-attribute 'highlight :foreground nil t)) + (set-face-attribute 'lsp-ui-peek-header nil + :background (face-attribute 'highlight :background nil t) + :foreground (face-attribute 'default :foreground nil t)) + ) diff --git a/layers/+tools/lsp/packages.el b/layers/+tools/lsp/packages.el new file mode 100644 index 000000000..a3c219713 --- /dev/null +++ b/layers/+tools/lsp/packages.el @@ -0,0 +1,67 @@ +(defconst lsp-packages + '( + (company-lsp :requires company) + (helm-xref :requires helm) + (ivy-xref :requires ivy) + lsp-mode + lsp-ui + )) + +(defun lsp/init-company-lsp () + (use-package company-lsp + :defer t + :init + ;; Language servers have better idea filtering and sorting, + ;; don't filter results on the client side. + (setq company-transformers nil + company-lsp-async t + company-lsp-cache-candidates nil) + ;; (spacemacs|add-company-backends :backends company-lsp :modes c-mode-common) + )) + +(defun lsp/init-helm-xref () + (use-package helm-xref + :defer t + :init + (progn + ;; This is required to make xref-find-references not give a prompt. + ;; xref-find-references asks the identifier (which has no text property) and then passes it to lsp-mode, which requires the text property at point to locate the references. + ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29619 + (setq xref-prompt-for-identifier + '(not xref-find-definitions xref-find-definitions-other-window xref-find-definitions-other-frame xref-find-references spacemacs/jump-to-definition)) + + ;; Use helm-xref to display xref.el results. + (setq xref-show-xrefs-function #'helm-xref-show-xrefs) + ))) + +(defun lsp/init-ivy-xref () + (use-package ivy-xref + :defer t + :init + (progn + (setq xref-prompt-for-identifier + '(not xref-find-definitions xref-find-definitions-other-window xref-find-definitions-other-frame xref-find-references spacemacs/jump-to-definition)) + + ;; Use ivy-xref to display xref.el results. + (setq xref-show-xrefs-function #'ivy-xref-show-xrefs) + ))) + +(defun lsp/init-lsp-mode () + (use-package lsp-mode + :config + (progn + (add-hook 'lsp-mode-hook #'lsp-ui-mode) + + ;; Disable lsp-flycheck.el in favor of lsp-ui-flycheck.el + (setq lsp-enable-flycheck nil) + + (spacemacs|diminish lsp-mode " Ⓛ" " L") + ))) + +(defun lsp/init-lsp-ui () + (use-package lsp-ui + :config + (progn + (lsp//sync-peek-face) + (add-hook 'spacemacs-post-theme-change-hook #'lsp//sync-peek-face) + )))