About an year ago, when it became clear that sooner or later I'll have to write ES6 code, I decided to give js2-mode another look (wow, how time flies!)
Steve Yegge no longer seems to maintain this majestic creation, but as it often happens in the open-source world, quality code finds new home and maintainers. The official fork today is located at https://github.com/mooz/js2-mode, and it's what you get if you install it from Melpa. However, I live on my own fork where I fix bugs as I find them. Eventually, my fixes get merged into the official repo.
On top of
code. It brings new powers at your fingertips — for example, you can select a piece of code and turn it into a
function; it figures out what are the variables needed by that piece of code, and turns them into arguments of the new
function; and replaces that piece of code with a call to the new function, which is inserted just outside the current
function. All that happens in a split second — an operation that would take many seconds to do manually. If you edit
Before switching to
js2-refactor, I had some utilities for editing JS that worked with an external parser (based
on UglifyJS). I have ported these tools on top of
js2-refactor, so we don't need
to call an external parser, and we get support for ES6. I wanted to briefly cover it in this post, and perhaps if more
people are interested I will submit a pull request to
These tools live in my fork of js2-refactor, on branch
highlights. It could have been a separated package (maybe it will, someday), but it was more convenient
for me to work on the same codebase as
js2-refactor, as I found several bugs (fixes already merged into
the official repo).
If you load
js2-refactor from that branch, the following utilities are available:
js2r-highlight-thing-at-point: with the cursor over a variable, it will highlight all occurrences of that variable in its defining scope. This is nice if you want to see quickly where is some variable used. It's, of course, smarter than a string search — it doesn't search for that name in strings or comments; in fact, it doesn't do any text search at all — instead, it uses the mighty power the parser to dig variable usage in the AST.
For convenience, this function does what you'd expect also on names like
super. It also works on constants (strings or numbers), in which case it highlights occurrences in the whole buffer.
While this mode is active, you can press
js2r-highlight-rename) to rename the variable. This duplicates a feature that
js2-refactoralready had (renaming variables), but the way my function does it is a little different (it asks for the new name in the minibuffer; the operation is undoable in a single step; it also works on strings or numbers, or on
this— which is sometimes convenient; and it tells you how many replacements were made).
js2r-highlight-free-vars: highlights “free variables” in the innermost function containing the cursor. Free variables are variables defined elsewhere (e.g. in some enclosing scope outside the current function). It's useful to know what are the free variables when you want to move a function around (for example a function with no free variables can be safely lifted to an upper scope). A short summary is displayed in the minibuffer (total free variable occurrences, and individually, their name and usage count).
js2r-highlight-exits: highlight exit points from the function surrounding the cursor. That is,
throwstatements. This becomes really useful when you work with code containing huge functions (hundreds of lines). I commonly do that — the fact that a function is huge doesn't mean everything happens in a gigantic mess of
for-s — the code is split into many subfunctions, which work together, sharing the environment, to achieve some goal. This kind of code is easier to write and understand, IMO, but you do need tools that enable you to reason about it, like, finding free variables, finding variable usage, or exit points.1
No keybindings are defined by default. My own preference is opinionated and based on years of usage and muscle memory — here's what I use, in my own Emacs config:
(define-key js2-refactor-mode-map (kbd "M-?") 'js2r-highlight-thing-at-point) (define-key js2-refactor-mode-map (kbd "C-c f") 'js2r-highlight-free-vars) (define-key js2-refactor-mode-map (kbd "C-c C-f") 'js2r-highlight-free-vars) (define-key js2-refactor-mode-map (kbd "C-c C-x") 'js2r-highlight-exits)
However, when highlights are on, a minor mode will be active which does define a bunch of key bindings:
(,(kbd "C-<down>") . js2r-highlight-move-next) (,(kbd "C-<up>") . js2r-highlight-move-prev) (,(kbd "C-<return>") . js2r-highlight-rename) (,(kbd "<escape>") . js2r-highlight-forgetit) (,(kbd "C-g") . js2r-highlight-forgetit)
So, you can use
Ctrl-Down to jump to the previous or next highlighted area,
Ctrl-Enter to rename variables (note this only makes sense if the mode was entered with
Esc to quit this minor mode and
remove the highlights.
Emacs rocks. Steve rocks. Magnar rocks. Mooz rocks. And if you find my little highlights mode useful, means I rock a little too, so please drop me a line. ;-)