From f3ee2edf1b8f4829d7b6c7e1804e1341d538e11a Mon Sep 17 00:00:00 2001 From: Ting Zhou Date: Thu, 26 Apr 2018 16:33:41 -0700 Subject: [PATCH] Add: add lsp-javascript backend for javascript layer --- layers/+lang/javascript/README.org | 46 +++++++++++++++--- layers/+lang/javascript/config.el | 4 ++ layers/+lang/javascript/funcs.el | 75 ++++++++++++++++++++++++++++- layers/+lang/javascript/packages.el | 25 +++++----- 4 files changed, 128 insertions(+), 22 deletions(-) diff --git a/layers/+lang/javascript/README.org b/layers/+lang/javascript/README.org index f70606961..05cfa5b0b 100644 --- a/layers/+lang/javascript/README.org +++ b/layers/+lang/javascript/README.org @@ -6,8 +6,11 @@ - [[#description][Description]] - [[#features][Features:]] - [[#install][Install]] -- [[#configuration][Configuration]] + - [[#choosing-a-backend][Choosing a backend]] +- [[#backends][Backends]] - [[#tern][Tern]] + - [[#language-server-protocol][Language Server Protocol]] +- [[#configuration][Configuration]] - [[#indentation][Indentation]] - [[#repl][REPL]] - [[#node-modules][Node Modules]] @@ -39,12 +42,6 @@ To use this configuration layer, add it to your =~/.spacemacs=. You will need to add =javascript= to the existing =dotspacemacs-configuration-layers= list in this file. -You will also need to install =tern= to use the auto-completion and -documentation features: -#+BEGIN_SRC sh - $ npm install -g tern -#+END_SRC - To use the formatting features, install =js-beautify=: #+BEGIN_SRC sh $ npm install -g js-beautify @@ -63,8 +60,33 @@ If you install these in non-standard locations, then add the following to your = (add-to-list 'exec-path "/path/to/node/bins" t) #+END_SRC -* Configuration +** Choosing a backend +To choose a default backend set the layer variable =javascript-backend=: + +#+BEGIN_SRC elisp +(javascript :variables javascript-backend 'tern) +#+END_SRC + +Backend can be chosen on a per project basis using directory local variables +(files named =.dir-locals.el= at the root of a project), an example to use the +=lsp= backend: + +#+BEGIN_SRC elisp +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((js2-mode (javascript-backend . lsp))) +#+END_SRC + +*Note:* you can easily add a directory local variable with ~SPC f v d~. + +* Backends ** Tern +Install =tern= to use the auto-completion and documentation features: +#+BEGIN_SRC sh + $ npm install -g tern +#+END_SRC + To make tern re-use the server across multiple different editing sessions (thus creating multiple =.tern-port= files for each document you have open [[http://ternjs.net/doc/manual.html][see here for more details]]): @@ -85,6 +107,14 @@ layer: (javascript :variables tern-command '("node" "/path/to/tern/bin/tern")) #+END_SRC +** Language Server Protocol +You just have to install python language server package: + +#+begin_src sh +npm i -g typescript javascript-typescript-langserver flow-language-server typescript-language-server +#+end_src + +* Configuration ** Indentation To change how js2-mode indents code, set the variable =js2-basic-offset=, as such: diff --git a/layers/+lang/javascript/config.el b/layers/+lang/javascript/config.el index d1e74ae02..cdae234d3 100644 --- a/layers/+lang/javascript/config.el +++ b/layers/+lang/javascript/config.el @@ -15,3 +15,7 @@ (defvar javascript-disable-tern-port-files t "Stops tern from creating tern port files.") + +(defvar javascript-backend 'tern + "The backend to use for IDE features. Possible values are `tern' +and `lsp'.") diff --git a/layers/+lang/javascript/funcs.el b/layers/+lang/javascript/funcs.el index a93d6cdd7..f41ad10f7 100644 --- a/layers/+lang/javascript/funcs.el +++ b/layers/+lang/javascript/funcs.el @@ -80,13 +80,44 @@ (skewer-repl) (evil-insert-state)) + +;; backend + +(defun spacemacs//javascript-setup-backend () + "Conditionally setup javascript backend." + (pcase javascript-backend + (`tern(spacemacs//javascript-setup-tern)) + (`lsp (spacemacs//javascript-setup-lsp)))) + +(defun spacemacs//javascript-setup-company () + "Conditionally setup company based on backend." + (pcase javascript-backend + (`tern (spacemacs//javascript-setup-tern-company)) + (`lsp (spacemacs//javascript-setup-lsp-company)))) + ;; tern +(defun spacemacs//javascript-setup-tern () + "Setup tern backend." + (add-hook 'js2-mode-hook 'tern-mode) + (progn + (spacemacs|hide-lighter tern-mode) + (when javascript-disable-tern-port-files + (add-to-list 'tern-command "--no-port-file" 'append)) + (spacemacs//set-tern-key-bindings 'js2-mode))) + +(defun spacemacs//javascript-setup-tern-company () + "Setup tern auto-completion." + (spacemacs|add-company-backends + :backends company-tern + :modes js2-mode) + (company-mode)) + (defun spacemacs//set-tern-key-bindings (mode) "Set the key bindings for tern and the given MODE." (add-to-list (intern (format "spacemacs-jump-handlers-%S" mode)) - '(tern-find-definition :async t)) + '(tern-find-definition :async t)) (spacemacs/set-leader-keys-for-major-mode mode "rrV" 'tern-rename-variable "hd" 'tern-get-docs @@ -100,3 +131,45 @@ (unless found (spacemacs-buffer/warning "tern binary not found!")) found)) + + +;; lsp + +(defun spacemacs//javascript-setup-lsp () + "Setup lsp backend." + (if (configuration-layer/layer-used-p 'lsp) + (progn + (add-hook 'js-mode-hook #'lsp-javascript-typescript-enable) + (require 'lsp-javascript-flow) + (add-hook 'js-mode-hook #'lsp-javascript-flow-enable) + (add-hook 'js2-mode-hook #'lsp-javascript-flow-enable) ;; for js2-mode support + (require 'lsp-typescript) + (add-hook 'js-mode-hook #'lsp-typescript-enable) + (add-hook 'js2-mode-hook #'lsp-typescript-enable) ;; for js2-mode support + (spacemacs//set-lsp-key-bindings 'js2-mode)) + (message "`lsp' layer is not installed, please add `lsp' layer to your dofile."))) + +(defun spacemacs//javascript-setup-lsp-company () + "Setup lsp auto-completion." + (if (configuration-layer/layer-used-p 'lsp) + (progn + ;; fix lsp-javascript company prefix + ;; https://github.com/emacs-lsp/lsp-javascript/issues/9#issuecomment-379515379 + (defun my-company-transformer (candidates) + (let ((completion-ignore-case t)) + (all-completions (company-grab-symbol) candidates))) + (defun my-js-hook nil + (make-local-variable 'company-transformers) + (push 'my-company-transformer company-transformers)) + (add-hook 'js-mode-hook 'my-js-hook) + + (spacemacs|add-company-backends + :backends company-lsp + :modes js2-mode) + (company-mode)) + (message "`lsp' layer is not installed, please add `lsp' layer to your dofile."))) + +(defun spacemacs//set-lsp-key-bindings (mode) + "Set the key bindings for tern and the given MODE." + (add-to-list (intern (format "spacemacs-jump-handlers-%S" mode)) + '(lsp-ui-peek-find-definitions))) diff --git a/layers/+lang/javascript/packages.el b/layers/+lang/javascript/packages.el index 2536df594..8395feba0 100644 --- a/layers/+lang/javascript/packages.el +++ b/layers/+lang/javascript/packages.el @@ -30,6 +30,7 @@ web-beautify skewer-mode livid-mode + (lsp-javascript-typescript :requires lsp-mode) )) (defun javascript/post-init-add-node-modules-path () @@ -66,12 +67,10 @@ (use-package company-tern :if (and (configuration-layer/package-used-p 'company) (configuration-layer/package-used-p 'tern)) - :defer t - :init (spacemacs|add-company-backends - :backends company-tern - :modes js2-mode))) + :defer t)) (defun javascript/post-init-company () + (add-hook 'js2-mode-hook #'spacemacs//javascript-setup-company) (spacemacs|add-company-backends :backends company-capf :modes coffee-mode)) @@ -104,7 +103,9 @@ (progn (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode)) ;; Required to make imenu functions work correctly - (add-hook 'js2-mode-hook 'js2-imenu-extras-mode)) + (add-hook 'js2-mode-hook 'js2-imenu-extras-mode) + ;; setup javascript backend + (add-hook 'js2-mode-hook 'spacemacs//javascript-setup-backend)) :config (progn ;; prefixes @@ -193,14 +194,7 @@ (defun javascript/init-tern () (use-package tern - :defer t - :init (add-hook 'js2-mode-hook 'tern-mode) - :config - (progn - (spacemacs|hide-lighter tern-mode) - (when javascript-disable-tern-port-files - (add-to-list 'tern-command "--no-port-file" 'append)) - (spacemacs//set-tern-key-bindings 'js2-mode)))) + :defer t)) (defun javascript/init-web-beautify () (use-package web-beautify @@ -253,3 +247,8 @@ :documentation "Live evaluation of JS buffer change." :evil-leader-for-mode (js2-mode . "Tl")) (spacemacs|diminish livid-mode " 🅻" " [l]")))) + +(defun javascript/init-lsp-javascript-typescript () + (use-package lsp-javascript-typescript + :commands lsp-javascript-typescript-enable + :defer t))