|
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.4.3">Jekyll</generator><link href="https://emacs.cafe/feed.xml" rel="self" type="application/atom+xml" /><link href="https://emacs.cafe/" rel="alternate" type="text/html" /><updated>2017-06-14T10:02:44+02:00</updated><id>https://emacs.cafe/</id><title type="html">Emacs café</title><subtitle>A blog about Emacs, mostly focused on JavaScript development, by Nicolas Petton.
|
|
</subtitle><entry><title type="html">Indium 0.6 is out!</title><link href="https://emacs.cafe/indium/emacs/javascript/2017/05/31/indium-0.6-released.html" rel="alternate" type="text/html" title="Indium 0.6 is out!" /><published>2017-05-31T15:10:00+02:00</published><updated>2017-05-31T15:10:00+02:00</updated><id>https://emacs.cafe/indium/emacs/javascript/2017/05/31/indium-0.6-released</id><content type="html" xml:base="https://emacs.cafe/indium/emacs/javascript/2017/05/31/indium-0.6-released.html"><p><a href="https://github.com/NicolasPetton/Indium">Indium</a> – the JavaScript development
|
|
environment for Emacs – version 0.6 has just been released!</p>
|
|
|
|
<p>This release brings a lot of improvements and polish:</p>
|
|
|
|
<ul>
|
|
<li>The stepping debugger now shows exceptions inline in the source;</li>
|
|
<li>Breakpoints can now be <a href="https://indium.readthedocs.io/en/latest/">activated and deactivated</a>;</li>
|
|
<li>Indium supports <a href="https://indium.readthedocs.io/en/latest/code-evaluation.html#adding-and-removing-breakpoints">live code updates</a> (hot-swapping JavaScript);</li>
|
|
<li>NodeJS integration has been <a href="https://indium.readthedocs.io/en/latest/setup.html#nodejs">greatly improved</a>.</li>
|
|
</ul>
|
|
|
|
<p>Installation and update instructions can be found in
|
|
the <a href="https://indium.readthedocs.io/en/latest/">documentation</a>. You can also check out the project on <a href="https://github.com/NicolasPetton/Indium">GitHub</a>.</p>
|
|
|
|
<p>Many thanks to <a href="https://github.com/TatriX">Tatrix</a> for his contributions to this release!</p></content><author><name>Nicolas Petton</name></author><summary type="html">Indium – the JavaScript development environment for Emacs – version 0.6 has just been released!</summary></entry><entry><title type="html">How to find all unused functions in JS buffers</title><link href="https://emacs.cafe/emacs/javascript/2017/05/12/finding-unused-functions.html" rel="alternate" type="text/html" title="How to find all unused functions in JS buffers" /><published>2017-05-12T14:43:00+02:00</published><updated>2017-05-12T14:43:00+02:00</updated><id>https://emacs.cafe/emacs/javascript/2017/05/12/finding-unused-functions</id><content type="html" xml:base="https://emacs.cafe/emacs/javascript/2017/05/12/finding-unused-functions.html"><p>The real power of Emacs lies in its extensibility. To be able to quickly hack
|
|
some Elisp together to fix a specific problem right in your development
|
|
environment is something quite unique to Emacs, and it makes it stand apart from
|
|
other text editors.</p>
|
|
|
|
<p>I’m working on a fairly large JavaScript code base for which maintenance can
|
|
sometimes be an issue.</p>
|
|
|
|
<p>Yesterday I wanted to quickly find all function definitions in a JavaScript file
|
|
that were not referenced anymore in the project, so I decided to hack some
|
|
Elisp to do that.</p>
|
|
|
|
<h2 id="what-do-we-already-have">What do we already have?</h2>
|
|
|
|
<p>Let’s see what building blocks are already available.</p>
|
|
|
|
<p><a href="https://github.com/nicolaspetton/xref-js2">xref-js2</a> makes it easy to find all
|
|
references to a specific function within a project,
|
|
and <a href="https://github.com/mooz/js2-mode">js2-mode</a> exposes an AST that can be
|
|
visited.</p>
|
|
|
|
<p>All in all, what I want to achieve shouldn’t be too hard to implement!</p>
|
|
|
|
<h2 id="first-steps">First steps</h2>
|
|
|
|
<p>I’m calling my small package <code class="highlighter-rouge">js2-unused</code>, so all functions and variables will
|
|
have that prefix.</p>
|
|
|
|
<p>We’ll need some packages along the way, so let’s require them:</p>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">require</span> <span class="ss">'seq</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nb">require</span> <span class="ss">'xref-js2</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nb">require</span> <span class="ss">'subr-x</span><span class="p">)</span></code></pre></figure>
|
|
|
|
<p>The first step is to find all function definitions within the current buffer.
|
|
<code class="highlighter-rouge">JS2-mode</code> has a function <code class="highlighter-rouge">js2-visit-ast</code> that makes it really easy to traverse
|
|
the entire AST tree.</p>
|
|
|
|
<p>We can first define a variable that will hold all function definition names that
|
|
we find:</p>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">defvar</span> <span class="nv">js2-unused-definitions</span> <span class="no">nil</span><span class="p">)</span></code></pre></figure>
|
|
|
|
<p>Now let’s traverse the AST and find all function definitions. We want to find:</p>
|
|
|
|
<ul>
|
|
<li>all assignments that assign to a function;</li>
|
|
<li>all function declarations that are named (skipping anonymous functions).</li>
|
|
</ul>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">defun</span> <span class="nv">js2-unused--find-definitions</span> <span class="p">()</span>
|
|
<span class="c1">;; Reset the value before visiting the AST</span>
|
|
<span class="p">(</span><span class="k">setq</span> <span class="nv">js2-unused-definitions</span> <span class="no">nil</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">js2-visit-ast</span> <span class="nv">js2-mode-ast</span>
|
|
<span class="nf">#'</span><span class="nv">js2-unused-visitor</span><span class="p">))</span>
|
|
|
|
<span class="p">(</span><span class="nb">defun</span> <span class="nv">js2-unused-visitor</span> <span class="p">(</span><span class="nv">node</span> <span class="nv">end-p</span><span class="p">)</span>
|
|
<span class="s">"Add NODE's name to `js2-unused-definitions` if it is a function."</span>
|
|
<span class="p">(</span><span class="nb">unless</span> <span class="nv">end-p</span>
|
|
<span class="p">(</span><span class="nb">cond</span>
|
|
<span class="c1">;; assignment to a function</span>
|
|
<span class="p">((</span><span class="nb">and</span> <span class="p">(</span><span class="nv">js2-assign-node-p</span> <span class="nv">node</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">js2-function-node-p</span> <span class="p">(</span><span class="nv">js2-assign-node-right</span> <span class="nv">node</span><span class="p">)))</span>
|
|
<span class="p">(</span><span class="nb">push</span> <span class="p">(</span><span class="nv">js2-node-string</span> <span class="p">(</span><span class="nv">js2-assign-node-left</span> <span class="nv">node</span><span class="p">))</span> <span class="nv">js2-unused-definitions</span><span class="p">))</span>
|
|
<span class="c1">;; function declaration (skipping anonymous ones)</span>
|
|
<span class="p">((</span><span class="nv">js2-function-node-p</span> <span class="nv">node</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">if-let</span> <span class="p">((</span><span class="nv">name</span> <span class="p">(</span><span class="nv">js2-function-name</span> <span class="nv">node</span><span class="p">)))</span>
|
|
<span class="p">(</span><span class="nb">push</span> <span class="nv">name</span> <span class="nv">js2-unused-definitions</span><span class="p">))))</span>
|
|
<span class="no">t</span><span class="p">))</span></code></pre></figure>
|
|
|
|
<h2 id="finding-references-using-xref-js2">Finding references using xref-js2</h2>
|
|
|
|
<p>Now that we can find and store all function names in a list, let’s use
|
|
<code class="highlighter-rouge">xref-js2</code> to filter the ones that are never referenced. If we find
|
|
unreferenced functions, we simply display a message listing them.</p>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">defun</span> <span class="nv">js2-unused-functions</span> <span class="p">()</span>
|
|
<span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
|
|
<span class="c1">;; Make sure that JS2 has finished parsing the buffer</span>
|
|
<span class="p">(</span><span class="nv">js2-mode-wait-for-parse</span>
|
|
<span class="p">(</span><span class="k">lambda</span> <span class="p">()</span>
|
|
<span class="c1">;; Walk the AST tree to find all function definitions</span>
|
|
<span class="p">(</span><span class="nv">js2-unused--find-definitions</span><span class="p">)</span>
|
|
<span class="c1">;; Use xref-js2 to filter the ones that are not referenced anywhere</span>
|
|
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">unused</span> <span class="p">(</span><span class="nv">seq-filter</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">name</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nb">null</span> <span class="p">(</span><span class="nv">xref-js2--find-references</span>
|
|
<span class="p">(</span><span class="nv">js2-unused--unqualified-name</span> <span class="nv">name</span><span class="p">))))</span>
|
|
<span class="nv">js2-unused-definitions</span><span class="p">)))</span>
|
|
<span class="c1">;; If there are unreferenced function, display a message</span>
|
|
<span class="p">(</span><span class="nb">apply</span> <span class="nf">#'</span><span class="nv">message</span> <span class="p">(</span><span class="k">if</span> <span class="nv">unused</span>
|
|
<span class="o">`</span><span class="p">(</span><span class="s">"Unused functions in %s: %s "</span>
|
|
<span class="o">,</span><span class="p">(</span><span class="nv">file-name-nondirectory</span> <span class="nv">buffer-file-name</span><span class="p">)</span>
|
|
<span class="o">,</span><span class="p">(</span><span class="nv">mapconcat</span> <span class="nf">#'</span><span class="nb">identity</span> <span class="nv">unused</span> <span class="s">" "</span><span class="p">))</span>
|
|
<span class="o">'</span><span class="p">(</span><span class="s">"No unused function found"</span><span class="p">)))))))</span>
|
|
|
|
<span class="p">(</span><span class="nb">defun</span> <span class="nv">js2-unused--unqualified-name</span> <span class="p">(</span><span class="nv">name</span><span class="p">)</span>
|
|
<span class="s">"Return the local name of NAME.
|
|
foo.bar.baz =&gt; baz"</span>
|
|
<span class="p">(</span><span class="nv">save-match-data</span>
|
|
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">string-match</span> <span class="s">"\\.\\([^.]+\\)$"</span> <span class="nv">name</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">match-string</span> <span class="mi">1</span> <span class="nv">name</span><span class="p">)</span>
|
|
<span class="nv">name</span><span class="p">)))</span></code></pre></figure>
|
|
|
|
<h2 id="conclusion">Conclusion</h2>
|
|
|
|
<p>That’s it! In ~30 lines we can now find unreferenced functions in any JS file.
|
|
Sure, the code is not perfect, far from it, but it was hacked together in 10
|
|
minutes and gets the job done.</p>
|
|
|
|
<p>Quickly writing some lisp code to fix a specific problem is something I do very
|
|
often. Most of the time, it’s code I throw away as soon as the task is
|
|
completed, but from time to time it’s something generic enough to be reused
|
|
later, in which case I save it in my <code class="highlighter-rouge">emacs.d</code>, or make a proper package out of
|
|
it.</p>
|
|
|
|
<p>If you find this feature useful, you can grab it from
|
|
my
|
|
<a href="https://gitlab.petton.fr/nico/emacs.d/blob/master/local-packages/js2-unused.el">emacs.d</a>.</p></content><author><name>Nicolas Petton</name></author><summary type="html">The real power of Emacs lies in its extensibility. To be able to quickly hack some Elisp together to fix a specific problem right in your development environment is something quite unique to Emacs, and it makes it stand apart from other text editors.</summary></entry><entry><title type="html">Setting up Emacs for JavaScript (part #2)</title><link href="https://emacs.cafe/emacs/javascript/setup/2017/05/09/emacs-setup-javascript-2.html" rel="alternate" type="text/html" title="Setting up Emacs for JavaScript (part #2)" /><published>2017-05-09T17:00:00+02:00</published><updated>2017-05-09T17:00:00+02:00</updated><id>https://emacs.cafe/emacs/javascript/setup/2017/05/09/emacs-setup-javascript-2</id><content type="html" xml:base="https://emacs.cafe/emacs/javascript/setup/2017/05/09/emacs-setup-javascript-2.html"><p>This is the second part of my series of articles describing how to make Emacs a
|
|
great JavaScript development environment. This time we’ll focus on getting good
|
|
auto-completion with type inference.</p>
|
|
|
|
<p>If you haven’t read it yet, you should jump to
|
|
the <a href="/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html">first post</a>
|
|
first to get things started.</p>
|
|
|
|
<h2 id="setting-up-tern--company-mode-for-auto-completion">Setting up Tern &amp; company-mode for auto-completion</h2>
|
|
|
|
<p><a href="https://ternjs.net">Tern</a> is a great tool once setup correctly. It parses
|
|
JavaScript files in a project and does type inference to provide meaningful
|
|
completion (with type hints) and support for cross-references.</p>
|
|
|
|
<p>Unfortunately, cross-references with tern never reliably worked for me, that’s
|
|
why I have always been
|
|
using <a href="https://github.com/nicolaspetton/xref-js2">xref-js2</a> instead for that
|
|
(see <a href="/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html">part #1</a>).</p>
|
|
|
|
<p>For auto-completion, we’ll be using company-mode with tern. Let’s go ahead and
|
|
install tern:</p>
|
|
|
|
<div class="highlighter-rouge"><pre class="highlight"><code>$ sudo npm install -g tern
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>Now let’s install the Emacs packages:</p>
|
|
|
|
<div class="highlighter-rouge"><pre class="highlight"><code>M-x package-install RET company-tern RET
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>The Emacs configuration is straight-forward, we simply enable company-mode with
|
|
the tern backend for JavaScript buffers:</p>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">require</span> <span class="ss">'company-mode</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nb">require</span> <span class="ss">'company-tern</span><span class="p">)</span>
|
|
|
|
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'company-backends</span> <span class="ss">'company-tern</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'js2-mode-hook</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">()</span>
|
|
<span class="p">(</span><span class="nv">tern-mode</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">company-mode</span><span class="p">)))</span>
|
|
|
|
<span class="c1">;; Disable completion keybindings, as we use xref-js2 instead</span>
|
|
<span class="p">(</span><span class="nv">define-key</span> <span class="nv">tern-mode-keymap</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">define-key</span> <span class="nv">tern-mode-keymap</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span></code></pre></figure>
|
|
|
|
<p>Now, depending on your JavaScript project, you might want to setup tern to work
|
|
with your project structure. If completion doesn’t work out of the box using
|
|
tern defaults you will have to set it up using a <code class="highlighter-rouge">.tern-project</code> placed in the
|
|
root folder containing your JavaScript files.</p>
|
|
|
|
<p>Here’s an example setup for a project that uses <code class="highlighter-rouge">requirejs</code> and <code class="highlighter-rouge">jQuery</code>,
|
|
ignoring files from the <code class="highlighter-rouge">bower_components</code> directory:</p>
|
|
|
|
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
|
|
</span><span class="nt">"libs"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
|
|
</span><span class="s2">"jquery"</span><span class="w">
|
|
</span><span class="p">],</span><span class="w">
|
|
</span><span class="nt">"loadEagerly"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
|
|
</span><span class="s2">"./**/*.js"</span><span class="w">
|
|
</span><span class="p">],</span><span class="w">
|
|
</span><span class="nt">"dontLoad"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
|
|
</span><span class="s2">"./bower_components/"</span><span class="w">
|
|
</span><span class="p">],</span><span class="w">
|
|
</span><span class="nt">"plugins"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
|
|
</span><span class="nt">"requirejs"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
|
|
</span><span class="nt">"baseURL"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./"</span><span class="w">
|
|
</span><span class="p">}</span><span class="w">
|
|
</span><span class="p">}</span><span class="w">
|
|
</span><span class="p">}</span></code></pre></figure>
|
|
|
|
<p>Once setup, tern offers superb completion. Together with company-mode, you get
|
|
great context-based completion with type inference.</p>
|
|
|
|
<p><img src="/img/tern-company-mode.png" alt="Ternjs" /></p>
|
|
|
|
<p>When completing a function, you can hit <code class="highlighter-rouge">&lt;F1&gt;</code> to get its documentation:</p>
|
|
|
|
<p><img src="/img/tern-documentation.png" alt="Ternjs documentation" /></p>
|
|
|
|
<h2 id="until-next-time">Until next time</h2>
|
|
|
|
<p>In the next articles I’ll cover linting with Flycheck, <code class="highlighter-rouge">gulp</code> and <code class="highlighter-rouge">grunt</code>
|
|
integration into Emacs, and of course how to setup and
|
|
use <a href="https://indium.readthedocs.io">Indium</a>.</p></content><author><name>Nicolas Petton</name></author><summary type="html">This is the second part of my series of articles describing how to make Emacs a great JavaScript development environment. This time we’ll focus on getting good auto-completion with type inference.</summary></entry><entry><title type="html">Setting up Emacs for JavaScript (part #1)</title><link href="https://emacs.cafe/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html" rel="alternate" type="text/html" title="Setting up Emacs for JavaScript (part #1)" /><published>2017-04-23T14:50:00+02:00</published><updated>2017-04-23T14:50:00+02:00</updated><id>https://emacs.cafe/emacs/javascript/setup/2017/04/23/emacs-setup-javascript</id><content type="html" xml:base="https://emacs.cafe/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html"><p>There’s a lot that can be done to make Emacs a great tool for JavaScript
|
|
development. So much that I had to split it up into several posts.</p>
|
|
|
|
<p>In this first article we’ll see how to
|
|
setup <a href="https://github.com/mooz/js2-mode">js2-mode</a> and two other packages that
|
|
rely upon it: <a href="https://github.com/magnars/js2-refactor.el">js2-refactor</a>
|
|
and <a href="https://github.com/nicolaspetton/xref-js2">xref-js2</a>.</p>
|
|
|
|
<p>Emacs comes with a major mode for JavaScript named <code class="highlighter-rouge">js-mode</code>. While it is a
|
|
good major mode, we’ll be using <code class="highlighter-rouge">js2-mode</code> instead, an external package that
|
|
extends <code class="highlighter-rouge">js-mode</code> and provides a very interesting feature: instead of using
|
|
regular expressions, it parses buffers and builds an AST for things like syntax
|
|
highlighting. While diverging a bit from the traditional “Emacs way of doing
|
|
things”, this is really interesting, and used as the foundation for other
|
|
features like refactorings.</p>
|
|
|
|
<h2 id="setting-up-js2-mode">Setting up js2-mode</h2>
|
|
|
|
<p>If you haven’t done it already, you should first setup <code class="highlighter-rouge">package.el</code> to
|
|
use <a href="https://melpa.org">MELPA</a>, then install and setup <code class="highlighter-rouge">js2-mode</code> like the
|
|
following:</p>
|
|
|
|
<div class="highlighter-rouge"><pre class="highlight"><code>M-x package-install RET js2-mode RET
|
|
</code></pre>
|
|
</div>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">require</span> <span class="ss">'js2-mode</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'auto-mode-alist</span> <span class="o">'</span><span class="p">(</span><span class="s">"\\.js\\'"</span> <span class="o">.</span> <span class="nv">js2-mode</span><span class="p">))</span>
|
|
|
|
<span class="c1">;; Better imenu</span>
|
|
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'js2-mode-hook</span> <span class="nf">#'</span><span class="nv">js2-imenu-extras-mode</span><span class="p">)</span></code></pre></figure>
|
|
|
|
<h2 id="js2-refactor-and-xref-js2">js2-refactor and xref-js2</h2>
|
|
|
|
<p>Now that we’re using <code class="highlighter-rouge">js2-mode</code> for JavaScript buffers, let’s take advantage its
|
|
capabilities of and install two other
|
|
packages: <a href="https://github.com/magnars/js2-refactor.el">js2-refactor</a>
|
|
and <a href="https://github.com/nicolaspetton/xref-js2">xref-js2</a>.</p>
|
|
|
|
<p><code class="highlighter-rouge">js2-refactor</code> adds powerful refactorings based on the AST generated by
|
|
<code class="highlighter-rouge">js2-mode</code>, and <code class="highlighter-rouge">xref-js2</code> makes it easy to jump to function references or
|
|
definitions.</p>
|
|
|
|
<p><code class="highlighter-rouge">xref-js2</code> uses <code class="highlighter-rouge">ag</code> to perform searches, so you’ll need to install it as well.</p>
|
|
|
|
<div class="highlighter-rouge"><pre class="highlight"><code>M-x package-install RET js2-refactor RET
|
|
M-x package-install RET xref-js2 RET
|
|
</code></pre>
|
|
</div>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nb">require</span> <span class="ss">'js2-refactor</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nb">require</span> <span class="ss">'xref-js2</span><span class="p">)</span>
|
|
|
|
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'js2-mode-hook</span> <span class="nf">#'</span><span class="nv">js2-refactor-mode</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">js2r-add-keybindings-with-prefix</span> <span class="s">"C-c C-r"</span><span class="p">)</span>
|
|
<span class="p">(</span><span class="nv">define-key</span> <span class="nv">js2-mode-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-k"</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">js2r-kill</span><span class="p">)</span>
|
|
|
|
<span class="c1">;; js-mode (which js2 is based on) binds "M-." which conflicts with xref, so</span>
|
|
<span class="c1">;; unbind it.</span>
|
|
<span class="p">(</span><span class="nv">define-key</span> <span class="nv">js-mode-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span>
|
|
|
|
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'js2-mode-hook</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">()</span>
|
|
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'xref-backend-functions</span> <span class="nf">#'</span><span class="nv">xref-js2-xref-backend</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)))</span></code></pre></figure>
|
|
|
|
<p>Now that everything’s setup, let’s see how to use <code class="highlighter-rouge">js2-refactor</code> and <code class="highlighter-rouge">xref-js2</code>.</p>
|
|
|
|
<h2 id="using-js2-refactor">Using js2-refactor</h2>
|
|
|
|
<p><code class="highlighter-rouge">js2-refactor</code> is a JavaScript refactoring library for emacs.</p>
|
|
|
|
<p>It provides a collection of refactoring functions leveraging the AST provided by
|
|
<code class="highlighter-rouge">js2-mode</code>.</p>
|
|
|
|
<p>Refactorings go from inlining/extracting variables to converting ternary
|
|
operators to if statements.
|
|
The <a href="https://github.com/magnars/js2-refactor.el">README</a> provides the full list of
|
|
keybindings.</p>
|
|
|
|
<p>One minor tweak that I really couldn’t live without is binding <code class="highlighter-rouge">js2r-kill</code> to
|
|
<code class="highlighter-rouge">C-k</code> in JS buffers:</p>
|
|
|
|
<figure class="highlight"><pre><code class="language-elisp" data-lang="elisp"><span class="p">(</span><span class="nv">define-key</span> <span class="nv">js2-mode-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-k"</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">js2r-kill</span><span class="p">)</span></code></pre></figure>
|
|
|
|
<p>This command is very similar to killing in <code class="highlighter-rouge">paredit</code>: It kills up to the end of
|
|
the line, but always keeping the AST valid.</p>
|
|
|
|
<p>Here’s a usage example of <code class="highlighter-rouge">js2-refactor</code>: renaming a function parameter and
|
|
inlining a variable.</p>
|
|
|
|
<p><img src="/img/js2-refactorings.gif" alt="Refactorings" /></p>
|
|
|
|
<h2 id="using-xref-js2">Using xref-js2</h2>
|
|
|
|
<p><code class="highlighter-rouge">xref-js2</code> adds support for quickly jumping to function definitions or
|
|
references to JavaScript projects in Emacs (&gt;= 25.1).</p>
|
|
|
|
<p>Instead of using a tag system, it relies on <code class="highlighter-rouge">ag</code> to query the codebase of a
|
|
project.</p>
|
|
|
|
<ul>
|
|
<li><code class="highlighter-rouge">M-.</code> Jump to definition</li>
|
|
<li><code class="highlighter-rouge">M-?</code> Jump to references</li>
|
|
<li><code class="highlighter-rouge">M-,</code> Pop back to where <code class="highlighter-rouge">M-.</code> was last invoked.</li>
|
|
</ul>
|
|
|
|
<p>Here’s a usage example of <code class="highlighter-rouge">xref-js2</code>:</p>
|
|
|
|
<p><img src="/img/xref-jump-to-references.gif" alt="Jumping to references" /></p>
|
|
|
|
<h2 id="until-next-time">Until next time</h2>
|
|
|
|
<p>You should now have a decent setup for <code class="highlighter-rouge">js2-mode</code> and associated tools.</p>
|
|
|
|
<p>We still have a lot to explore like linting, getting good auto-completion, using
|
|
snippets, setting up a REPL and debugger, etc. but I promised I would keep posts
|
|
short, so stay tuned for part #2!</p></content><author><name>Nicolas Petton</name></author><summary type="html">There’s a lot that can be done to make Emacs a great tool for JavaScript development. So much that I had to split it up into several posts.</summary></entry><entry><title type="html">M-x hello-world</title><link href="https://emacs.cafe/jekyll/update/2017/04/21/hello-world.html" rel="alternate" type="text/html" title="M-x hello-world" /><published>2017-04-21T23:14:09+02:00</published><updated>2017-04-21T23:14:09+02:00</updated><id>https://emacs.cafe/jekyll/update/2017/04/21/hello-world</id><content type="html" xml:base="https://emacs.cafe/jekyll/update/2017/04/21/hello-world.html"><p>All blogs should begin with an introductory post, so here we go.</p>
|
|
|
|
<p>I’ve been willing to make a blog dedicated
|
|
to <a href="http://gnu.org/software/emacs">Emacs</a> for a long time, but until now I
|
|
couldn’t find the right topic.</p>
|
|
|
|
<p>This blog will have a focus on using Emacs as an environment for writing
|
|
JavaScript. I will talk about Emacs configurations specific to JavaScript and
|
|
packages that make Emacs the great and powerful IDE that it is for web
|
|
development.</p>
|
|
|
|
<p>I’ll try to keep all posts short and to the point, and I’ll most probably post
|
|
tutorial videos from time to time.</p>
|
|
|
|
<p>Topics might sometimes slip a bit from the original focus, but as long as it’s
|
|
about Emacs, I think it’ll be ok.</p></content><author><name>Nicolas Petton</name></author><summary type="html">All blogs should begin with an introductory post, so here we go.</summary></entry></feed>
|