2015-12-02 14:23:39 +00:00
#+TITLE : JavaScript layer
2015-06-10 16:44:30 +00:00
2019-05-07 08:53:56 +00:00
#+TAGS : general|js|layer|multi-paradigm|programming
2019-05-05 17:26:40 +00:00
2018-05-14 02:35:12 +00:00
[[file:img/javascript.png ]]
2015-06-10 16:44:30 +00:00
2019-05-07 20:05:06 +00:00
* Table of Contents :TOC_5_gh:noexport:
2017-05-22 14:16:12 +00:00
- [[#description ][Description ]]
- [[#features ][Features: ]]
- [[#install ][Install ]]
2018-05-18 05:15:03 +00:00
- [[#web-beautify ][web-beautify ]]
2018-06-19 06:25:33 +00:00
- [[#prettier ][prettier ]]
2019-04-13 01:59:47 +00:00
- [[#import-js ][import-js ]]
2018-04-26 23:33:41 +00:00
- [[#choosing-a-backend ][Choosing a backend ]]
2018-06-19 06:25:33 +00:00
- [[#choosing-a-formatter ][Choosing a formatter ]]
2019-10-09 16:58:43 +00:00
- [[#format-buffer-before-saving ][Format buffer before saving ]]
2018-04-26 23:33:41 +00:00
- [[#backends ][Backends ]]
2017-05-22 14:16:12 +00:00
- [[#tern ][Tern ]]
2018-04-26 23:33:41 +00:00
- [[#language-server-protocol ][Language Server Protocol ]]
2019-04-14 17:02:24 +00:00
- [[#debugger-dap-integration ][Debugger (dap integration) ]]
2018-04-26 23:33:41 +00:00
- [[#configuration ][Configuration ]]
2017-05-22 14:16:12 +00:00
- [[#indentation ][Indentation ]]
- [[#repl ][REPL ]]
2019-06-09 18:02:37 +00:00
- [[#browser-based-repl ][Browser based REPL ]]
- [[#server-based-repl ][Server based REPL ]]
2019-02-04 19:44:41 +00:00
- [[#node ][Node ]]
- [[#node-modules ][Node Modules ]]
- [[#node-externs ][Node Externs ]]
2018-12-05 03:03:03 +00:00
- [[#key-bindings ][Key bindings ]]
2017-05-22 14:16:12 +00:00
- [[#js2-mode ][js2-mode ]]
- [[#folding-js2-mode ][Folding (js2-mode) ]]
2018-06-05 05:57:25 +00:00
- [[#importing-import-js ][Importing (import-js) ]]
2017-05-22 14:16:12 +00:00
- [[#refactoring-js2-refactor ][Refactoring (js2-refactor) ]]
- [[#documentation-js-doc ][Documentation (js-doc) ]]
2019-06-09 18:02:37 +00:00
- [[#browser-based-repl-skewer-mode ][Browser based REPL (skewer-mode) ]]
- [[#server-based-repl-nodejs-repl ][Server based REPL (nodejs-repl) ]]
2019-04-14 17:02:24 +00:00
- [[#debugger-dap-mode ][debugger (dap mode) ]]
2015-06-10 16:44:30 +00:00
* Description
This layer adds support for the JavaScript language using [[https://github.com/mooz/js2-mode ][js2-mode ]].
2015-06-10 21:16:01 +00:00
** Features:
2018-05-08 04:10:48 +00:00
- Multiple backends support: Tern and LSP
2015-06-10 16:44:30 +00:00
- Smart code folding
- Refactoring: done using [[https://github.com/magnars/js2-refactor.el ][js2-refactor ]].
2018-05-13 14:15:47 +00:00
- Auto-completion and documentation
2019-06-09 18:02:37 +00:00
- Browser based REPL available via [[https://github.com/skeeto/skewer-mode ][skewer-mode ]] and [[https://github.com/pandeiro/livid-mode ][livid-mode ]]
- Server based REPL with [[https://github.com/abicky/nodejs-repl.el ][nodejs-repl ]]
2019-10-09 16:58:43 +00:00
- Formatting with [[https://github.com/yasuyk/web-beautify ][web-beautify ]] or [[https://github.com/prettier/prettier ][prettier ]]
2019-09-30 01:30:53 +00:00
- Interactive debugger using [[https://github.com/emacs-lsp/dap-mode ][dap-mode ]]
2016-01-16 13:35:07 +00:00
2015-06-10 16:44:30 +00:00
* Install
2016-01-06 05:21:55 +00:00
To use this configuration layer, add it to your =~/.spacemacs= . You will need to
2016-07-31 10:05:40 +00:00
add =javascript= to the existing =dotspacemacs-configuration-layers= list in
this file.
2015-06-10 16:44:30 +00:00
2018-06-05 05:57:25 +00:00
To enable the importing helper, install the =ImportJS= :
#+BEGIN_SRC sh
$ npm install -g import-js
#+END_SRC
2016-07-31 10:05:40 +00:00
To activate error checking using flycheck, install one of the [[http://www.flycheck.org/en/latest/languages.html#javascript ][available linters ]]
such as =ESLint= or =JSHint= :
2018-07-10 10:57:25 +00:00
2015-09-11 06:44:43 +00:00
#+BEGIN_SRC sh
2016-07-30 18:52:52 +00:00
$ npm install -g eslint
# or
2015-09-11 06:44:43 +00:00
$ npm install -g jshint
#+END_SRC
2019-10-09 16:58:43 +00:00
If you install these in non-standard locations, then add the following to your
=dotspacemacs/user-init= function:
2018-07-10 10:57:25 +00:00
2016-10-15 18:54:05 +00:00
#+BEGIN_SRC elisp
(add-to-list 'exec-path "/path/to/node/bins" t)
#+END_SRC
2018-05-18 05:15:03 +00:00
** web-beautify
2018-05-18 06:04:45 +00:00
See [[file:../../+tools/web-beautify/README.org ][web-beautify layer ]] documentation.
2018-05-18 05:15:03 +00:00
2018-06-19 06:25:33 +00:00
** prettier
See [[file:../../+tools/prettier/README.org ][prettier layer ]] documentation.
2019-04-13 01:59:47 +00:00
** import-js
See [[file:../../+tools/import-js/README.org ][import-js layer ]] documentation.
To enable it, set the layer variable =javascript-import-tool= :
#+BEGIN_SRC elisp
(javascript :variables javascript-import-tool 'import-js)
#+END_SRC
2018-04-26 23:33:41 +00:00
** Choosing a backend
To choose a default backend set the layer variable =javascript-backend= :
#+BEGIN_SRC elisp
2018-09-19 03:54:47 +00:00
(javascript :variables javascript-backend 'tern)
2018-04-26 23:33:41 +00:00
#+END_SRC
2019-09-30 04:49:44 +00:00
Alternatively the =lsp= backend will be automatically chosen if the layer =lsp=
is used and you did not specify any value for =javascript-backend= .
2018-04-26 23:33:41 +00:00
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
2018-09-19 03:54:47 +00:00
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
2018-04-26 23:33:41 +00:00
2018-09-19 03:54:47 +00:00
((js2-mode (javascript-backend . lsp)))
2018-04-26 23:33:41 +00:00
#+END_SRC
2019-04-13 07:12:06 +00:00
When =lsp= is set as the backend, but you don't want to use lsp as the linter,
set the variable =javascript-lsp-linter= to =nil= .
#+BEGIN_SRC elisp
2019-07-27 13:24:53 +00:00
(javascript :variables
javascript-backend 'lsp
javascript-lsp-linter nil)
2019-04-13 07:12:06 +00:00
#+END_SRC
2019-07-27 13:24:53 +00:00
2018-06-19 06:25:33 +00:00
** Choosing a formatter
To choose a formatter, set the layer variable =javascript-fmt-tool= :
#+BEGIN_SRC elisp
2018-09-19 03:54:47 +00:00
(javascript :variables javascript-fmt-tool 'web-beautify)
2018-06-19 06:25:33 +00:00
#+END_SRC
2019-10-09 16:58:43 +00:00
The formatter can be chosen on a per project basis using directory local
variables (files named =.dir-locals.el= at the root of a project). For example
to use the =prettier= formatter:
2018-06-19 06:25:33 +00:00
#+BEGIN_SRC elisp
2018-09-19 03:54:47 +00:00
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
2018-06-19 06:25:33 +00:00
2018-09-19 03:54:47 +00:00
((js2-mode (javascript-fmt-tool . prettier)))
2018-06-19 06:25:33 +00:00
#+END_SRC
2018-04-26 23:33:41 +00:00
*Note:* you can easily add a directory local variable with ~SPC f v d~ .
2019-04-24 12:03:27 +00:00
You can choose formatting tool:
#+BEGIN_SRC elisp
2019-04-27 00:15:28 +00:00
(setq-default dotspacemacs-configuration-layers '(
(javascript :variables
javascript-fmt-tool 'prettier)))
2019-04-24 12:03:27 +00:00
#+END_SRC
Default is =’ web-beautify= .
2019-10-09 16:58:43 +00:00
** Format buffer before saving
2019-11-08 16:03:53 +00:00
#+BEGIN_SRC elisp
2019-10-09 16:58:43 +00:00
(javascript :variables javascript-fmt-on-save t)
2019-11-08 16:03:53 +00:00
#+END_SRC
2019-10-09 16:58:43 +00:00
2018-04-26 23:33:41 +00:00
* Backends
2015-09-11 02:41:50 +00:00
** Tern
2018-05-18 06:21:05 +00:00
See [[file:../../+tools/tern/README.org ][tern layer ]] documentation.
2016-03-07 20:22:37 +00:00
2018-04-26 23:33:41 +00:00
** Language Server Protocol
2019-10-09 16:58:43 +00:00
You have to install =typescript-language-server= (recommended) or
=javascript-typescript-langserver= language server packages via
2019-04-17 13:48:54 +00:00
2019-04-14 17:02:24 +00:00
#+BEGIN_SRC sh
npm i -g typescript typescript-language-server
#+END_SRC
2019-04-17 13:48:54 +00:00
2019-04-14 17:02:24 +00:00
or
2019-04-17 13:48:54 +00:00
2018-09-19 03:54:47 +00:00
#+BEGIN_SRC sh
npm i -g typescript javascript-typescript-langserver
#+END_SRC
2018-04-26 23:33:41 +00:00
2019-04-14 17:02:24 +00:00
*** Debugger (dap integration)
2019-10-09 16:58:43 +00:00
To install the debug adapter you may run =M-x dap-firefox-setup= or
=M-x dap-chrome-setup= if you are using Linux or download it manually from
[[https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-firefox-debug ][Firefox Debug Adapter ]] or [[https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome ][Chrome Debug Adapter ]] and adjust
=dap-firefox-debug-path= or =dap-chrome-debug-path= . For usage instructions
refer to [[https://github.com/emacs-lsp/dap-mode ][dap-mode ]] readme.
2019-04-14 17:02:24 +00:00
2018-04-26 23:33:41 +00:00
* Configuration
2015-09-11 02:41:50 +00:00
** Indentation
2016-07-31 10:05:40 +00:00
To change how js2-mode indents code, set the variable =js2-basic-offset= , as
such:
2015-07-10 19:33:19 +00:00
#+BEGIN_SRC emacs-lisp
(setq-default js2-basic-offset 2)
#+END_SRC
2018-01-01 17:07:59 +00:00
or when adding the =javascript= configuration layer:
2018-07-10 10:57:25 +00:00
2018-01-01 17:07:59 +00:00
#+BEGIN_SRC emacs-lisp
(javascript :variables js2-basic-offset 2)
#+END_SRC
2015-10-20 12:30:21 +00:00
Similarly, to change how js-mode indents JSON files, set the variable
=js-indent-level= , as such:
2015-07-10 19:33:19 +00:00
#+BEGIN_SRC emacs-lisp
(setq-default js-indent-level 2)
#+END_SRC
2018-01-01 17:07:59 +00:00
or when adding the =javascript= configuration layer:
2018-07-10 10:57:25 +00:00
2018-01-01 17:07:59 +00:00
#+BEGIN_SRC emacs-lisp
(javascript :variables js-indent-level 2)
#+END_SRC
2015-09-11 02:41:50 +00:00
** REPL
2019-06-09 18:02:37 +00:00
*** Browser based REPL
To use the browser based REPL set the =javascript-repl= variable as shown below:
2019-06-09 19:54:33 +00:00
2019-06-09 18:02:37 +00:00
#+BEGIN_SRC elisp
(setq-default dotspacemacs-configuration-layers
'((javascript :variables javascript-repl `skewer)))
#+END_SRC
In addition you need a running httpd server and a page loaded
2016-07-31 10:05:40 +00:00
with skewer. If a blank page serves your needs, just use the run-skewer command
in your javascript buffer. If you want to inject it in your own page, follow
[[https://github.com/skeeto/skewer-mode#skewering-with-cors ][these instructions ]] (install the Greasemonkey script and then click the triangle
2019-05-26 20:58:52 +00:00
in the top-right corner - if it turns green, you're good to go).
2015-09-11 02:41:50 +00:00
2019-06-09 18:02:37 +00:00
*** Server based REPL
To use the server based REPL set the =javascript-repl= variable as shown below:
2019-06-09 19:54:33 +00:00
2019-06-09 18:02:37 +00:00
#+BEGIN_SRC elisp
(setq-default dotspacemacs-configuration-layers
'((javascript :variables javascript-repl `nodejs)))
#+END_SRC
In addition install nodejs and make sure that =node= is in the path.
2019-02-04 19:44:41 +00:00
** Node
*** Node Modules
2017-11-27 20:29:38 +00:00
If you would like =node_modules/.bin= to be automatically added to the buffer
local =exec_path= , e.g. to support project local eslint installations, set the
=node-add-modules-path= variable in the =javascript= config section. Note that
doing this [[https://stackoverflow.com/questions/9679932#comment33532258_9683472 ][introduces a security risk ]]:
#+BEGIN_SRC elisp
2018-09-19 03:54:47 +00:00
(setq-default dotspacemacs-configuration-layers
'((javascript :variables node-add-modules-path t)))
2017-11-27 20:29:38 +00:00
#+END_SRC
2019-02-04 19:44:41 +00:00
*** Node Externs
If you want =js2-mode= to presume =node= variables are defined by the host
system (for completion purposes /i.a./ ) set the =js2-include-node-exters=
variable to =t= in the =javascript= config section:
#+BEGIN_SRC elisp
(setq-default dotspacemacs-configuration-layers
'((javascript :variables js2-include-node-externs t)))
#+END_SRC
2018-12-05 03:03:03 +00:00
* Key bindings
2015-06-10 16:44:30 +00:00
** js2-mode
2018-12-05 03:03:03 +00:00
| Key binding | Description |
2015-07-05 19:27:32 +00:00
|-------------+--------------------------------------|
| ~SPC m w~ | toggle js2-mode warnings and errors |
| ~%~ | jump between blockswith [[https://github.com/redguardtoo/evil-matchit][evil-matchit]] |
2015-06-10 16:44:30 +00:00
** Folding (js2-mode)
2018-12-05 03:03:03 +00:00
| Key binding | Description |
2015-06-10 16:44:30 +00:00
|-------------+--------------------------|
| ~SPC m z c~ | hide element |
| ~SPC m z o~ | show element |
| ~SPC m z r~ | show all element |
| ~SPC m z e~ | toggle hide/show element |
| ~SPC m z F~ | toggle hide functions |
| ~SPC m z C~ | toggle hide comments |
2018-06-05 05:57:25 +00:00
** Importing (import-js)
2019-04-08 15:39:05 +00:00
| Key binding | Description |
2018-06-05 05:57:25 +00:00
|-------------+---------------------------------------------------------------------|
| ~SPC m i i~ | Import the module for the variable under the cursor |
| ~SPC m i f~ | Import any missing modules and remove any modules that are not used |
| ~SPC m g i~ | Go to the module of the variable under cursor |
2015-06-10 16:44:30 +00:00
** Refactoring (js2-refactor)
Bindings should match the plain emacs assignments.
2018-12-05 03:03:03 +00:00
| Key binding | Description |
2015-06-10 16:44:30 +00:00
|---------------+----------------------------------------------------------------------------------------------------------------|
| ~SPC m k~ | deletes to the end of the line, but does not cross semantic boundaries |
| ~SPC m r 3 i~ | converts ternary operator to if-statement |
| ~SPC m r a g~ | creates a =/* global */= annotation if it is missing, and adds var to point to it |
| ~SPC m r a o~ | replaces arguments to a function call with an object literal of named arguments |
| ~SPC m r b a~ | moves the last child out of current function, if-statement, for-loop or while-loop |
| ~SPC m r c a~ | converts a multiline array to one line |
| ~SPC m r c o~ | converts a multiline object literal to one line |
| ~SPC m r c u~ | converts a multiline function to one line (expecting semicolons as statement delimiters) |
| ~SPC m r e a~ | converts a one line array to multiline |
| ~SPC m r e f~ | extracts the marked expressions into a new named function |
| ~SPC m r e m~ | extracts the marked expressions out into a new method in an object literal |
| ~SPC m r e o~ | converts a one line object literal to multiline |
| ~SPC m r e u~ | converts a one line function to multiline (expecting semicolons as statement delimiters) |
| ~SPC m r e v~ | takes a marked expression and replaces it with a var |
| ~SPC m r i g~ | creates a shortcut for a marked global by injecting it in the wrapping immediately invoked function expression |
| ~SPC m r i p~ | changes the marked expression to a parameter in a local function |
| ~SPC m r i v~ | replaces all instances of a variable with its initial value |
| ~SPC m r l p~ | changes a parameter to a local var in a local function |
| ~SPC m r l t~ | adds a console.log statement for what is at point (or region) |
| ~SPC m r r v~ | renames the variable on point and all occurrences in its lexical scope |
| ~SPC m r s l~ | moves the next statement into current function, if-statement, for-loop, while-loop |
| ~SPC m r s s~ | splits a =String= |
| ~SPC m r s v~ | splits a =var= with multiple vars declared into several =var= statements |
| ~SPC m r t f~ | toggle between function declaration and function expression |
| ~SPC m r u w~ | replaces the parent statement with the selected region |
| ~SPC m r v t~ | changes local =var a= to be =this.a= instead |
| ~SPC m r w i~ | wraps the entire buffer in an immediately invoked function expression |
| ~SPC m r w l~ | wraps the region in a for-loop |
2016-06-10 04:09:42 +00:00
| ~SPC m x m j~ | move line down, while keeping commas correctly placed |
| ~SPC m x m k~ | move line up, while keeping commas correctly placed |
2015-06-10 16:44:30 +00:00
*** Documentation (js-doc)
You can check more [[https://github.com/mooz/js-doc/ ][here ]]
2018-12-05 03:03:03 +00:00
| Key binding | Description |
2015-06-10 16:44:30 +00:00
|---------------+---------------------------------------|
| ~SPC m r d b~ | insert JSDoc comment for current file |
| ~SPC m r d f~ | insert JSDoc comment for function |
| ~SPC m r d t~ | insert tag to comment |
| ~SPC m r d h~ | show list of available jsdoc tags |
2019-06-09 18:02:37 +00:00
** Browser based REPL (skewer-mode)
2015-09-11 02:41:50 +00:00
2018-12-05 03:03:03 +00:00
| Key binding | Description |
2016-01-21 16:50:51 +00:00
|-------------+------------------------------------------------------------------|
| ~SPC m e e~ | evaluates the last expression |
| ~SPC m e E~ | evaluates and inserts the result of the last expression at point |
2018-12-05 03:03:03 +00:00
| Key binding | Description |
2016-01-21 16:50:51 +00:00
|-------------+------------------------------------------------------------------------------------|
2019-06-01 12:41:17 +00:00
| ~SPC m T l~ | Toggle live evaluation of whole buffer in REPL on buffer changes |
2016-01-21 16:50:51 +00:00
| ~SPC m s b~ | send current buffer contents to the skewer REPL |
| ~SPC m s B~ | send current buffer contents to the skewer REPL and switch to it in insert state |
| ~SPC m s f~ | send current function at point to the skewer REPL |
| ~SPC m s F~ | send current function at point to the skewer REPL and switch to it in insert state |
| ~SPC m s i~ | starts/switch to the skewer REPL |
| ~SPC m s r~ | send current region to the skewer REPL |
| ~SPC m s R~ | send current region to the skewer REPL and switch to it in insert state |
| ~SPC m s s~ | switch to REPL |
2019-04-14 17:02:24 +00:00
2019-06-09 18:02:37 +00:00
** Server based REPL (nodejs-repl)
| Key binding | Description |
|-------------+--------------------------------------------------------------------|
| ~SPC m s i~ | Switch to NodeJS REPL if one has been started, otherwise start one |
| ~SPC m s e~ | Send last expression to NodeJS REPL |
| ~SPC m s E~ | Send last expression to NodeJS REPL and switch to REPL |
| ~SPC m s b~ | Send current buffer to NodeJS REPL |
| ~SPC m s B~ | Send current buffer to NodeJS REPL and switch to REPL |
| ~SPC m s l~ | Send current line to NodeJS REPL |
| ~SPC m s L~ | Send current line to NodeJS REPL and switch to REPL |
| ~SPC m s r~ | Send active region to NodeJS REPL |
| ~SPC m s R~ | Send active region to NodeJS REPL and switch to REPL |
2019-06-09 19:54:33 +00:00
| ~SPC m s s~ | switch to REPL |
2019-06-09 18:02:37 +00:00
2019-04-14 17:02:24 +00:00
** debugger (dap mode)
2019-09-30 01:30:53 +00:00
Using the =dap= layer you'll get access to all the DAP key bindings, see the
complete list of key bindings on the [[https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Btools/dap#key-bindings ][dap layer description ]].