Skip to content

Commit

Permalink
lsp-layer configuration and building blocks for derived layers.
Browse files Browse the repository at this point in the history
See README.org for details
  • Loading branch information
Cormac Cannon committed Mar 16, 2018
1 parent 0fa3658 commit 2067d72
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 40 deletions.
115 changes: 89 additions & 26 deletions layers/+tools/lsp/README.org
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,101 @@
- [[#description][Description]]
- [[#features][Features:]]
- [[#configuration][Configuration]]
- [[#derived-layers][Derived layers]]
- [[#spacemacslsp-append-jump-handlers-mode][=(spacemacs/lsp-append-jump-handlers mode)=]]
- [[#spacemacslsp-define-keys-for-mode-mode][=spacemacs/lsp-define-keys-for-mode mode=]]
- [[#variables][Variables]]
- [[#diagnostics][Diagnostics]]

* Description
This layer adds support for basic language server protocol packages speaking
[[https://microsoft.github.io/language-server-protocol/specification][language server protocol]].
This layer adds support for basic language server protocol packages speaking
[[https://microsoft.github.io/language-server-protocol/specification][language server protocol]].

Different language servers may support the language server protocol to varying degrees
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.

** 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.
- 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=)
- Navigation using imenu

* 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.
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.

** Derived layers
A number of elisp functions have been added to facilitate development of derived layers.

*** =(spacemacs/lsp-append-jump-handlers mode)=
Appends =lsp-ui-peek-find-definitions= to the list of jump-handlers for a given mode.

*** =spacemacs/lsp-define-keys-for-mode mode=
Binds keys to a number of lsp features useful for all/most modes for the given major mode.

Binds keys under the following prefixes:

| prefix | mnemonic |
|--------+------------|
| = | formatting |
| g | goto |
| l | lsp-ui |
| r | refactor |
| t | toggles |

The default bindings are listed below. Derived language server layers should extend this list.

| binding | function |
|---------+-------------------------------------------------|
| == | format buffer (lsp) |
|---------+-------------------------------------------------|
| gi | browse file symbols |
| gs | find workspace symbol |
| gf | find file at point |
|---------+-------------------------------------------------|
| li | browse file symbols |
| ld | find definitions |
| lr | find references |
| ls | find-workspace-symbol |
|---------+-------------------------------------------------|
| rr | rename |
|---------+-------------------------------------------------|
| td | toggle documentation overlay |
| tF | toggle documentation overlay function signature |
| ts | toggle symbol info overlay |
| tS | toggle symbol info overlay symbol name |
| tI | toggle symbol info overlay duplicates |

** Variables
A number of configuration variables have been exposed via the LSP layer =config.el=.
Sensible defaults have been provided, however they may all be overridden in your .spacemacs, or dynamically using the bindings added
under the derived mode t prefix by =(spacemacs/lsp-define-keys-for-mode mode)=

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.
| Variable name | Default | Description |
|-------------------------------+---------+-------------------------------------------------------------------------------------------|
| lsp-remap-xref-keybindings | nil | When non-nil, xref keybindings remapped to lsp-ui-peek-find-{definition,references} |
| lsp-ui-doc-enable | t | When non-nil, the documentation overlay is displayed |
| lsp-ui-doc-include-signature | nil | When nil, signature omitted from lsp-ui-doc overlay (this is usually redundant) |
| lsp-ui-sideline-enable | nil | When non-nil, the symbol information overlay is displayed |
| lsp-ui-sideline-show-symbol | nil | When non-nil, the symbol information overlay includes symbol name (redundant for c-modes) |
| lsp-ui-peek-expend-by-default | t | When non-nil, =lsp-ui-peek= overlay expands file matches automatically |

If some features doe not work as intended, here is a common check list.
** Diagnostics
If some features do not work as expected, 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
- =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
10 changes: 10 additions & 0 deletions layers/+tools/lsp/config.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
;; ;; TODO slow https://github.com/emacs-lsp/lsp-ui/issues/45
;; ;; (setq lsp-ui-flycheck-enable nil)
;; ;; These all have toggles bound under 't' in spacemacs/lsp-define-keys-for-mode
(defvar lsp-remap-xref-keybindings nil "When non-nil, xref keybindings remapped to lsp-ui-peek-find-*")
(defvar lsp-ui-peek-expand-by-default t "Expand lsp-ui-peek by default (may have performance implications)")
(defvar lsp-ui-doc-enable t "Enable/disable lsp-ui-doc overlay")
(defvar lsp-ui-doc-include-signature nil "Omit type signature in the lsp-ui-doc overlay")
(defvar lsp-ui-sideline-enable nil "Enable/disable lsp-ui-sideline overlay")
(defvar lsp-ui-sideline-show-symbol nil "When non-nil, sideline includes symbol info (largely redundant for c modes)") ; don't show symbol on the right of info
(defvar lsp-ui-sideline-ignore-duplicate t "Ignore duplicates")
78 changes: 77 additions & 1 deletion layers/+tools/lsp/funcs.el
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
;;
;; Copyright (c) 2012-2018 Sylvain Benner & Contributors
;;
;; Author: Fangrui Song <i@maskray.me>
;; Authors: Fangrui Song <i@maskray.me>, Cormac Cannon
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
Expand Down Expand Up @@ -30,3 +30,79 @@
:background (face-attribute 'highlight :background nil t)
:foreground (face-attribute 'default :foreground nil t))
)

(defun spacemacs/lsp-append-jump-handlers (mode)
;;; Override
(let ((handler (intern (format "spacemacs-jump-handlers-%s" mode))))
(add-to-list handler 'lsp-ui-peek-find-definitions))
;; The notion of 'spacemacs-reference-handlers' is the subject of this PR:
;; https://github.com/syl20bnr/spacemacs/pull/9911
;; Disabling for now...
;; (let ((handler (intern (format "spacemacs-reference-handlers-%s" mode))))
;; (add-to-list handler 'lsp-ui-peek-find-references))
)

(defun spacemacs/lsp-bind-keys-for-mode (mode)
"Define key bindings for the specific MODE."
(spacemacs/declare-prefix-for-mode mode "m=" "format")
(spacemacs/declare-prefix-for-mode mode "mg" "goto")
(spacemacs/declare-prefix-for-mode mode "ml" "lsp")
(spacemacs/declare-prefix-for-mode mode "mr" "refactor")
(spacemacs/declare-prefix-for-mode mode "mt" "toggle")

(spacemacs/set-leader-keys-for-major-mode mode
;;Format
"==" #'spacemacs/lsp-format-buffer
;;goto
"gi" #'imenu
"gs" #'lsp-ui-find-workspace-symbol
"gf" #'spacemacs/lsp-ffap-no-prompt
;;lsp
"li" #'lsp-ui-imenu
"ld" #'lsp-ui-peek-find-definitions
"lr" #'lsp-ui-peek-find-references
"ls" #'lsp-ui-peek-find-workspace-symbol
;;refactor
"rr" #'lsp-rename
;;toggles
"td" #'lsp-ui-doc-mode
"ts" #'lsp-ui-sideline-mode
"tF" #'spacemacs/lsp-ui-doc-func
"tS" #'spacemacs/lsp-ui-sideline-symb
"tI" #'spacemacs/lsp-ui-sideline-ignore-duplicate
)

)


(defun spacemacs/lsp-ui-doc-func ()
"Toggle the function signature in the lsp-ui-doc overlay"
(interactive)
(setq lsp-ui-doc-include-signature (not lsp-ui-doc-include-signature)))

(defun spacemacs/lsp-ui-sideline-symb ()
"Toggle the symbol in the lsp-ui-sideline overlay.
(generally redundant in C modes)"
(interactive)
(setq lsp-ui-sideline-show-symbol (not lsp-ui-sideline-show-symbol)))

(defun spacemacs/lsp-ui-sideline-ignore-duplicate ()
"Toggle ignore duplicates for lsp-ui-sideline overlay"
(interactive)
(setq lsp-ui-sideline-ignore-duplicate (not lsp-ui-sideline-ignore-duplicate)))

(defun spacemacs/lsp-ffap-no-prompt ()
"find-file-at-point, suppressing the prompt when file not found"
(interactive)
(-if-let ((filename (ffap-guess-file-name-at-point)))
(ffap filename)
(user-error "No file at point")))

;; Used for lsp-ui-peek-mode, but may be able to use some spacemacs fn. instead?
(defun spacemacs/lsp-define-key (keymap key def &rest bindings)
"Define multiple key bindings with KEYMAP KEY DEF BINDINGS."
(interactive)
(while key
(define-key keymap (kbd key) def)
(setq key (pop bindings)
def (pop bindings))))
52 changes: 39 additions & 13 deletions layers/+tools/lsp/packages.el
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
;;
;; Copyright (c) 2012-2018 Sylvain Benner & Contributors
;;
;; Author: Fangrui Song <i@maskray.me>
;; Authors: Fangrui Song <i@maskray.me>, Cormac Cannon
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
Expand All @@ -11,15 +11,17 @@

(defconst lsp-packages
'(
(company-lsp :requires company)
;; `flycheck-lsp' does not exist so we defined it as built-in to avoid
;; fetching it from ELPA repositories.
;; this logical package serves to hook all flycheck related configuration
;; for LSP.
(flycheck-lsp :requires flycheck :location built-in)
lsp-mode
lsp-ui
))
(company-lsp :requires company)
;; `flycheck-lsp' does not exist so we defined it as built-in to avoid
;; fetching it from ELPA repositories.
;; this logical package serves to hook all flycheck related configuration
;; for LSP.
(flycheck-lsp :requires flycheck :location built-in)
lsp-mode
lsp-ui
(lsp-imenu :requires imenu :location built-in)
(lsp-ui-imenu :requires lsp-imenu :location built-in)
))

(defun lsp/init-company-lsp ()
(use-package company-lsp
Expand All @@ -28,24 +30,48 @@
;; 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)))
company-lsp-async t
company-lsp-cache-candidates nil)))

(defun lsp/init-flycheck-lsp ()
;; Disable lsp-flycheck.el in favor of lsp-ui-flycheck.el
(setq lsp-enable-flycheck nil))

(defun lsp/init-lsp-mode ()
(use-package lsp-mode
:defer t
:config
(progn
(spacemacs|hide-lighter lsp-mode))))

(defun lsp/init-lsp-ui ()
(use-package lsp-ui
:defer t
:init (add-hook 'lsp-mode-hook #'lsp-ui-mode)
:config
(progn
(spacemacs//lsp-sync-peek-face)
(add-hook 'spacemacs-post-theme-change-hook
#'spacemacs//lsp-sync-peek-face))))
#'spacemacs//lsp-sync-peek-face))

(if lsp-ui-peek-expand-by-default
(setq lsp-ui-peek-expand-function (lambda (xs) (mapcar #'car xs))))

(if lsp-remap-xref-keybindings
(progn (define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
(define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)))

(spacemacs/lsp-define-key
lsp-ui-peek-mode-map
"h" #'lsp-ui-peek--select-prev-file
"j" #'lsp-ui-peek--select-next
"k" #'lsp-ui-peek--select-prev
"l" #'lsp-ui-peek--select-next-file
)
))

(defun lsp/init-lsp-imenu ()
(use-package lsp-imenu :defer t :init (add-hook 'lsp-after-open-hook #'lsp-enable-imenu)))

(defun lsp/init-lsp-ui-imenu ()
(use-package lsp-ui-imenu :defer t :config (evil-make-overriding-map lsp-ui-imenu-mode-map)))

0 comments on commit 2067d72

Please sign in to comment.