Unlike other language development, JavaScript, for me, has two components, a front-end, browser-based interface, as well as a back-end, server-side interface through Node.
I like the extras found in Steve Yegge’s js2-mode.
(use-package js2-mode
:ensure t
:init
(setq js-basic-indent 2)
(setq-default js2-basic-indent 2
js2-basic-offset 2
js2-auto-indent-p t
js2-cleanup-whitespace t
js2-enter-indents-newline t
js2-indent-on-enter-key t
js2-global-externs (list "window" "module" "require" "buster" "sinon" "assert" "refute" "setTimeout" "clearTimeout" "setInterval" "clearInterval" "location" "__dirname" "console" "JSON" "jQuery" "$"))
(add-hook 'js2-mode-hook
(lambda ()
(push '("function" . ?ƒ) prettify-symbols-alist)))
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)))
Color defined variables with color-identifiers-mode:
(use-package color-identifiers-mode
:ensure t
:init
(add-hook 'js2-mode-hook 'color-identifiers-mode))
While editing JavaScript is baked into Emacs, it is quite important
to have flycheck validate the source based on jshint, and eslint.
Let’s prefer eslint
:
(add-hook 'js2-mode-hook
(lambda () (flycheck-select-checker "javascript-eslint")))
Now load and edit a JavaScript file, like jshint-code-test.js.
The Tern project is a JavaScript analyzer that can be used to improve the JavaScript integration with editors like Emacs.
(use-package tern
:ensure t
:init (add-hook 'js2-mode-hook (lambda () (tern-mode t)))
:config
(use-package company-tern
:ensure t
:init (add-to-list 'company-backends 'company-tern)))
The following additional keys are bound:
M-.
- Jump to the definition of the thing under the cursor.
- M-,
- Brings you back to last place you were when you pressed
M-.
. C-c C-r
- Rename the variable under the cursor.
C-c C-c
- Find the type of the thing under the cursor.
C-c C-d
- Find docs of the thing under the cursor. Press again to open the associated URL (if any).
The js2-refactor mode should start with C-c .
and then a two-letter
mnemonic shortcut.
ef
isextract-function
: Extracts the marked expressions out into a new named function.em
isextract-method
: Extracts the marked expressions out into a new named method in an object literal.ip
isintroduce-parameter
: Changes the marked expression to a parameter in a local function.lp
islocalize-parameter
: Changes a parameter to a local var in a local function.eo
isexpand-object
: Converts a one line object literal to multiline.co
iscontract-object
: Converts a multiline object literal to one line.eu
isexpand-function
: Converts a one line function to multiline (expecting semicolons as statement delimiters).cu
iscontract-function
: Converts a multiline function to one line (expecting semicolons as statement delimiters).ea
isexpand-array
: Converts a one line array to multiline.ca
iscontract-array
: Converts a multiline array to one line.wi
iswrap-buffer-in-iife
: Wraps the entire buffer in an immediately invoked function expressionig
isinject-global-in-iife
: Creates a shortcut for a marked global by injecting it in the wrapping immediately invoked function expressionag
isadd-to-globals-annotation
: Creates a/*global */
annotation if it is missing, and adds the var at point to it.ev
isextract-var
: Takes a marked expression and replaces it with a var.iv
isinline-var
: Replaces all instances of a variable with its initial value.rv
isrename-var
: Renames the variable on point and all occurrences in its lexical scope.vt
isvar-to-this
: Changes localvar a
to bethis.a
instead.ao
isarguments-to-object
: Replaces arguments to a function call with an object literal of named arguments. Requires yasnippets.3i
isternary-to-if
: Converts ternary operator to if-statement.sv
issplit-var-declaration
: Splits avar
with multiple vars declared, into severalvar
statements.uw
isunwrap
: Replaces the parent statement with the selected region.
(use-package js2-refactor
:ensure t
:init (add-hook 'js2-mode-hook 'js2-refactor-mode)
:config (js2r-add-keybindings-with-prefix "C-c ."))
I also configure Skewer for my HTML and CSS files, we need to do the same for JavaScript:
(use-package skewer-mode
:ensure t
:init (add-hook 'js2-mode-hook 'skewer-mode))
Kick things off with run-skewer
, and then:
- C-x C-e
- `skewer-eval-last-expression’
- C-M-x
- `skewer-eval-defun’
- C-c C-k
- `skewer-load-buffer’
Using the coffee-mode for CoffeeScript file.
(use-package coffee-mode
:ensure t
:init
(setq-default coffee-tab-width 2))
Need to remember the following keybindings:
Return
- Insert newline and indent line
C-c C-<, backtab
- Indent line or region to left
C-c C->
- Indent line or region to right
A-r, C-c C-k
- Compile buffer to JavaScript
A-R
- Compile content of region to JavaScript
A-M-r, C-c C-z
- Run CoffeeScript REPL
C-c C-l
- Send this line to REPL buffer
C-c C-r
- Send content of region to REPL buffer
C-c C-b
- Send content of buffer to REPL buffer
C-c C-o C-s
- Enable coffee-cos-mode
(use-package ob-coffee
:ensure t)
Make sure that we can simply require
this library.
(provide 'init-javascript)
Before you can build this on a new system, make sure that you put
the cursor over any of these properties, and hit: C-c C-c