You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1364 lines
132 KiB

<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.5.1">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>2018-06-12T21:24:33+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">Using Ledger for YNAB-like envelope budgeting</title><link href="https://emacs.cafe/ledger/emacs/ynab/budgeting/2018/06/12/elbank-ynab.html" rel="alternate" type="text/html" title="Using Ledger for YNAB-like envelope budgeting" /><published>2018-06-12T21:20:00+02:00</published><updated>2018-06-12T21:20:00+02:00</updated><id>https://emacs.cafe/ledger/emacs/ynab/budgeting/2018/06/12/elbank-ynab</id><content type="html" xml:base="https://emacs.cafe/ledger/emacs/ynab/budgeting/2018/06/12/elbank-ynab.html">&lt;h1 id=&quot;bye-bye-elbank&quot;&gt;Bye bye Elbank&lt;/h1&gt;
&lt;p&gt;I have to start this post with this: I will not be actively maintaining
&lt;a href=&quot;https://github.com/NicolasPetton/elbank&quot;&gt;Elbank&lt;/a&gt; anymore, simply because I
switched back to &lt;a href=&quot;https://www.ledger-cli.org/&quot;&gt;Ledger&lt;/a&gt;. If someone wants to
take over, please contact me!&lt;/p&gt;
&lt;p&gt;The main reason for switching is budgeting. While Elbank was a cool experiment,
it is not an accounting software, and inherently lacks support for powerful
budgeting.&lt;/p&gt;
&lt;p&gt;When I started working on Elbank as a replacement for Ledger, I was looking for
a reporting tool within Emacs that would fetch bank transactions automatically,
so I wouldn’t have to enter transactions by hand (this is a seriously tedious
task, and I grew tired of doing it after roughly two years, and finally gave up).&lt;/p&gt;
&lt;p&gt;Since then, I learned about ledger-autosync and boobank, which I use to sync my
bank statements with Ledger (more about that in another post).&lt;/p&gt;
&lt;h1 id=&quot;ynabs-way-of-budgeting&quot;&gt;YNAB’s way of budgeting&lt;/h1&gt;
&lt;p&gt;I only came across &lt;a href=&quot;https://ynab.com&quot;&gt;YNAB&lt;/a&gt; recently. While I won’t use their
software (being a non-free web application, and, you know… there’s no &lt;code class=&quot;highlighter-rouge&quot;&gt;M-x
ynab&lt;/code&gt;), I think that the principles behind it are really appealing for personal
budgeting. I encourage you to &lt;a href=&quot;https://www.youneedabudget.com/method/&quot;&gt;read more about
it&lt;/a&gt; (or grab a &lt;a href=&quot;https://www.youneedabudget.com/book-order-now/&quot;&gt;copy of the
book&lt;/a&gt;, it’s great), but here’s
the idea.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Budget every euro&lt;/strong&gt;: Quite simple once you get it. Every single Euro you have
should be in a budget envelope. You should assign a job to every Euro you
earn (that’s called
&lt;a href=&quot;https://en.wikipedia.org/wiki/Zero-based_budgeting&quot;&gt;zero-based&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Envelope_system&quot;&gt;envelope
system&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Embrace your true expenses&lt;/strong&gt;: Plan for larger and less frequent expenses, so
when a yearly bill arrives, or your car breaks down, you’ll be covered.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Roll with the punches&lt;/strong&gt;: Address overspending as it happens by taking money
overspent from another envelope. As long as you keep budgeting, you’re
succeeding.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Age your money&lt;/strong&gt;: Spend less than you earn, so your money stays in the bank
account longer. As you do that, the age of your money will grow, and once
you reach the goal of spending money that is at least one month old, you
won’t worry about that next bill.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;implementation-in-ledger&quot;&gt;Implementation in Ledger&lt;/h1&gt;
&lt;p&gt;I assume that you are familiar with Ledger, but if not I recommend reading its
great
&lt;a href=&quot;https://www.ledger-cli.org/3.0/doc/ledger3.html#Introduction-to-Ledger&quot;&gt;introduction&lt;/a&gt;
and &lt;a href=&quot;https://www.ledger-cli.org/3.0/doc/ledger3.html#Ledger-Tutorial&quot;&gt;tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The implementation in Ledger uses plain double-entry accounting. I took most of
it from
&lt;a href=&quot;http://sachachua.com/blog/2014/11/keeping-financial-score-ledger/&quot;&gt;Sacha&lt;/a&gt;, with
some minor differences.&lt;/p&gt;
&lt;h2 id=&quot;budgeting-new-money&quot;&gt;Budgeting new money&lt;/h2&gt;
&lt;p&gt;After each income transaction, I budget the new money:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2018-06-12 Employer
Assets:Bank:Checking 1600.00 EUR
Income:Salary -1600.00 EUR
2018-06-12 Budget
[Assets:Budget:Food] 400.00 EUR
[Assets:Budget:Rent] 600.00 EUR
[Assets:Budget:Utilities] 600.00 EUR
[Equity:Budget] -1600.00 EUR
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Did you notice the square brackets around the accounts of the budget
transaction? It’s a feature Ledger calls &lt;a href=&quot;https://www.ledger-cli.org/3.0/doc/ledger3.html#Virtual-postings&quot;&gt;virtual
postings&lt;/a&gt;. These
postings are not considered real, and won’t be present in any report that uses
the &lt;code class=&quot;highlighter-rouge&quot;&gt;--real&lt;/code&gt; flag. This is exactly what we want, since it’s a budget allocation
and not a “real” transaction. Therefore we’ll use the &lt;code class=&quot;highlighter-rouge&quot;&gt;--real&lt;/code&gt; flag for all
reports except for our budget report.&lt;/p&gt;
&lt;h2 id=&quot;automatically-crediting-budget-accounts-when-spending-money&quot;&gt;Automatically crediting budget accounts when spending money&lt;/h2&gt;
&lt;p&gt;Next, we need to credit the budget accounts each time we spend money. Ledger
has another neat feature called &lt;a href=&quot;https://www.ledger-cli.org/3.0/doc/ledger3.html#Automated-Transactions&quot;&gt;automated
transactions&lt;/a&gt;
for this:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;= /Expenses/
[Assets:Budget:Unbudgeted] -1.0
[Equity:Budget] 1.0
= /Expenses:Food/
[Assets:Budget:Food] -1.0
[Assets:Budget:Unbudgeted] 1.0
= /Expenses:Rent/
[Assets:Budget:Rent] -1.0
[Assets:Budget:Unbudgeted] 1.0
= /Expenses:Utilities/
[Assets:Budget:Utilities] -1.0
[Assets:Budget:Unbudgeted] 1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Every expense is taken out of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Assets:Budget:Unbudgeted&lt;/code&gt; account by default.&lt;/p&gt;
&lt;p&gt;This forces me to budget properly, as &lt;code class=&quot;highlighter-rouge&quot;&gt;Assets:Budget:Unbudgeted&lt;/code&gt; should always
be 0 (if it is not the case I immediately know that there is something wrong
going on).&lt;/p&gt;
&lt;p&gt;All other automatic transactions take money out of the
&lt;code class=&quot;highlighter-rouge&quot;&gt;Assets:Budget:Unbudgeted&lt;/code&gt; account instead of &lt;code class=&quot;highlighter-rouge&quot;&gt;Equity:Budget&lt;/code&gt; account.&lt;/p&gt;
&lt;h2 id=&quot;a-budget-report&quot;&gt;A Budget report&lt;/h2&gt;
&lt;p&gt;This is the final piece of the puzzle. Here’s the budget report command:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ledger --empty -S -T -f ledger.dat bal ^assets:budget
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If we have the following transactions:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2018/06/12 Groceries store
Expenses:Food 123.00 EUR
Assets:Bank:Checking
2018/06/12 Landlord
Expenses:Rent 600.00 EUR
Assets:Bank:Checking
2018/06/12 Internet provider
Expenses:Utilities:Internet 40.00 EUR
Assets:Bank:Checking
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here’s what the report looks like:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 837.00 EUR Assets:Budget
560.00 EUR Utilities
277.00 EUR Food
0 Rent
0 Unbudgeted
--------------------
837.00 EUR
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Ledger is amazingly powerful, and provides a great framework for YNAB-like
budgeting. In a future post I’ll explain how I automatically import my bank
transactions using a mix of &lt;code class=&quot;highlighter-rouge&quot;&gt;ledger-autosync&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;weboob&lt;/code&gt;.&lt;/p&gt;</content><author><name>Nicolas Petton</name></author><summary type="html">Bye bye Elbank</summary></entry><entry><title type="html">Introducing Elbank</title><link href="https://emacs.cafe/elbank/emacs/2017/11/30/elbank-intro.html" rel="alternate" type="text/html" title="Introducing Elbank" /><published>2017-11-30T14:28:00+01:00</published><updated>2017-11-30T14:28:00+01:00</updated><id>https://emacs.cafe/elbank/emacs/2017/11/30/elbank-intro</id><content type="html" xml:base="https://emacs.cafe/elbank/emacs/2017/11/30/elbank-intro.html">&lt;p&gt;&lt;a href=&quot;https://github.com/NicolasPetton/elbank&quot;&gt;Elbank&lt;/a&gt; is a new Emacs package I’ve
been working on lately. It’s a &lt;em&gt;personal finances&lt;/em&gt; and &lt;em&gt;budgeting&lt;/em&gt; package for
Emacs that uses &lt;a href=&quot;https://weboob.org&quot;&gt;Weboob&lt;/a&gt; for scraping data from bank
websites.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/elbank-overview.png&quot; alt=&quot;Overview buffer&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I started building Elbank after using &lt;a href=&quot;https://github.com/ledger/ledger&quot;&gt;Ledger&lt;/a&gt;
for several years. While Ledger is a real gem, I didn’t want to spend time
doing bookkeeping anymore.&lt;/p&gt;
&lt;p&gt;Instead, I wanted a simple reporting tool that would automatically scrap data
and build reports within Emacs from it.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-weboob&quot;&gt;Setting up Weboob&lt;/h2&gt;
&lt;p&gt;To use Elbank, you will first have to &lt;a href=&quot;https://weboob.org/install&quot;&gt;install
Weboob&lt;/a&gt;. Weboob is a collection of applications
used to interact with websites from the command-line. Elbank uses the banking
application named &lt;code class=&quot;highlighter-rouge&quot;&gt;boobank&lt;/code&gt; to scrap data.&lt;/p&gt;
&lt;p&gt;The list of currently supported bank websites is available &lt;a href=&quot;http://weboob.org/applications/boobank&quot;&gt;on this
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fortunately, installing Weboob should be a breeze as there are
&lt;a href=&quot;http://weboob.org/install&quot;&gt;packages&lt;/a&gt; for most GNU/Linux distros, and an
&lt;a href=&quot;http://formulae.brew.sh/formula/weboob&quot;&gt;homebrew formula&lt;/a&gt; for Mac users.&lt;/p&gt;
&lt;p&gt;Once Weboob is installed, run &lt;code class=&quot;highlighter-rouge&quot;&gt;boobank&lt;/code&gt; in a console to setup your accounts.&lt;/p&gt;
&lt;h2 id=&quot;installing-elbank&quot;&gt;Installing Elbank&lt;/h2&gt;
&lt;p&gt;You can now install elbank from &lt;a href=&quot;https://melpa.org&quot;&gt;MELPA&lt;/a&gt;&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; by
running &lt;code class=&quot;highlighter-rouge&quot;&gt;M-x package-install RET elbank RET&lt;/code&gt;, and voila!&lt;/p&gt;
&lt;h2 id=&quot;using-elbank&quot;&gt;Using Elbank&lt;/h2&gt;
&lt;h3 id=&quot;the-overview-buffer&quot;&gt;The overview buffer&lt;/h3&gt;
&lt;p&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;M-x elbank-overview&lt;/code&gt; to get started. The overview buffer lists all
accounts as custom reports and budgets.&lt;/p&gt;
&lt;p&gt;Press &lt;code class=&quot;highlighter-rouge&quot;&gt;u&lt;/code&gt; to import the bank statements from your bank website.&lt;/p&gt;
&lt;p&gt;You can click on each account or report displayed in the buffer to open them.&lt;/p&gt;
&lt;h2 id=&quot;categorizing-transactions&quot;&gt;Categorizing transactions&lt;/h2&gt;
&lt;p&gt;Transaction categories is an important aspect of Elbank. Categories make it
possible to filter and budget.&lt;/p&gt;
&lt;p&gt;Transactions are automatically categorized when reporting, using the custom
variable &lt;code class=&quot;highlighter-rouge&quot;&gt;elbank-categories&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here’s an example value for &lt;code class=&quot;highlighter-rouge&quot;&gt;elbank-categories&lt;/code&gt;, you should adjust it based on
your own transactions and categorizing needs.&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elbank-categories&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expenses:Food&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^supermarket&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;^restaurant&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Local store XXX&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Bakery XXX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expenses:Rent&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Real Estate Agency XXX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Income:Salary&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bank transfer from Company XXX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Each transaction’s text is matched against the regular expressions of
&lt;code class=&quot;highlighter-rouge&quot;&gt;elbank-categories&lt;/code&gt;, the first match defines the category of a transaction.&lt;/p&gt;
&lt;h3 id=&quot;reports&quot;&gt;Reports&lt;/h3&gt;
&lt;p&gt;Evaluate &lt;code class=&quot;highlighter-rouge&quot;&gt;M-x elbank-report&lt;/code&gt; to create a new report. The command will ask you
for an account, period and category, which are all optional.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/elbank-report-example.png&quot; alt=&quot;Report&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here’s the list of keybindings available in a report buffer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f c&lt;/code&gt;: Filter the transactions by category&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f a&lt;/code&gt;: Only show transactions in a specified account&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f p&lt;/code&gt;: Select the period of the report&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;G&lt;/code&gt;: Group transactions by some property&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt;: Sort transactions&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;s&lt;/code&gt;: Reverse the sort order&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;M-p&lt;/code&gt;: Move backward by one period (month or year)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;M-n&lt;/code&gt;: Move forward by one period (month or year)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also customize the variable &lt;code class=&quot;highlighter-rouge&quot;&gt;elbank-saved-monthly-reports&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;elbank-saved-yearly-reports&lt;/code&gt; to conveniently get a quick list of commonly used
reports from the overview buffer.&lt;/p&gt;
&lt;h3 id=&quot;budgeting&quot;&gt;Budgeting&lt;/h3&gt;
&lt;p&gt;The custom variable &lt;code class=&quot;highlighter-rouge&quot;&gt;elbank-budget&lt;/code&gt; is used to define a monthy budget. It
defines how much money we want to spend by category of transaction, like
&lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;Food&quot;&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;Rent&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elbank-budget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expenses:Food&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expenses:Rent&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;450&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expenses:Transport&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Expenses:Utilities&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;145&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that budgeted amounts are positive numbers while expenses have negative
values.&lt;/p&gt;
&lt;p&gt;Press &lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt; from the overview buffer or evaluate &lt;code class=&quot;highlighter-rouge&quot;&gt;M-x elbank-budget-report&lt;/code&gt; to see
your expenses based on your budget.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/elbank-budget-report.png&quot; alt=&quot;Budget report&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can switch periods with &lt;code class=&quot;highlighter-rouge&quot;&gt;M-p&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;M-n&lt;/code&gt; the same way as in report buffers.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That’s all for now!&lt;/p&gt;
&lt;p&gt;Elbank is still in its infancy, but I’m already using it daily. If you find any
bug or would like to suggest improvements, feel free to open a ticket on the
&lt;a href=&quot;https://github.com/NicolasPetton/elbank&quot;&gt;GitHub project&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:1&quot;&gt;
&lt;p&gt;As of today, the package is not yet in MELPA, but a &lt;a href=&quot;https://github.com/melpa/melpa/pull/5157&quot;&gt;pull
request&lt;/a&gt; is in review to add it to
the repository.&amp;nbsp;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><author><name>Nicolas Petton</name></author><summary type="html">Elbank is a new Emacs package I’ve been working on lately. It’s a personal finances and budgeting package for Emacs that uses Weboob for scraping data from bank websites.</summary></entry><entry><title type="html">beginend.el</title><link href="https://emacs.cafe/emacs/package/2017/08/01/beginend.html" rel="alternate" type="text/html" title="beginend.el" /><published>2017-08-01T10:38:00+02:00</published><updated>2017-08-01T10:38:00+02:00</updated><id>https://emacs.cafe/emacs/package/2017/08/01/beginend</id><content type="html" xml:base="https://emacs.cafe/emacs/package/2017/08/01/beginend.html">&lt;p&gt;Thank you Nicolas for letting me borrow (again) your blog to talk
about my work. This time, this will not only be my work, but the one
of Matus Goljer too (aka &lt;a href=&quot;https://github.com/Fuco1/&quot;&gt;Fuco1&lt;/a&gt;). Let me
present &lt;a href=&quot;https://github.com/DamienCassou/beginend&quot;&gt;beginend&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;genesis&quot;&gt;Genesis&lt;/h2&gt;
&lt;p&gt;Four years ago, I started being really annoyed by the fact that &lt;code class=&quot;highlighter-rouge&quot;&gt;M-&amp;lt;&lt;/code&gt;
would go to the beginning of the dired buffer instead of the first
file as shown in this picture:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/beginend-dired-notes.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I then wrote these lines of Emacs-lisp code to fix this.&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dired-back-to-top&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beginning-of-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dired-next-line&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dired-omit-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dired-mode-map&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;vector&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'remap&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'beginning-of-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'dired-back-to-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At this time, I took the same approach to bind &lt;code class=&quot;highlighter-rouge&quot;&gt;M-&amp;lt;&lt;/code&gt; so that point
would go to the beginning of an email body instead of before headers:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mu4e-compose-goto-top&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;old-position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message-goto-body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;old-position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beginning-of-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mu4e-compose-mode-map&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;vector&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'remap&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'beginning-of-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'mu4e-compose-goto-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can see that this one is a bit smarter. The function moves point
to the beginning of a message’s body, but if point is already there,
the point is moved to the buffer’s real beginning instead. This makes
it possible to press &lt;code class=&quot;highlighter-rouge&quot;&gt;M-&amp;lt;&lt;/code&gt; several times to switch between the real
buffer beginning and the meaningful one. I called this feature
&lt;em&gt;double-tap&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I did the same for &lt;code class=&quot;highlighter-rouge&quot;&gt;M-&amp;gt;&lt;/code&gt; and this served me well for the next two
years.&lt;/p&gt;
&lt;h2 id=&quot;start-of-the-beginend-project&quot;&gt;Start of the beginend project&lt;/h2&gt;
&lt;p&gt;Two years ago, I started cleaning my &lt;a href=&quot;https://github.com/DamienCassou/emacs.d&quot;&gt;init.el&lt;/a&gt; file and decided to
extract useful bits of Emacs Lisp code into separate packages. That
was the beginning of the beginend project.&lt;/p&gt;
&lt;p&gt;I also took the opportunity to improve the code to avoid duplication
by introducing a macro:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;beginend-message-goto-beginning&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Go to the beginning of an email, after the headers.&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beginend--double-tap-begin&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message-goto-body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defmacro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;beginend--double-tap-begin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;amp;rest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Evaluate &amp;amp;BODY and goto real beginning if that did not change point.&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tempvar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;make-symbol&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;old-position&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tempvar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;,@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tempvar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;call-interactively&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beginning-of-buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The function &lt;code class=&quot;highlighter-rouge&quot;&gt;beginend-message-goto-beginning&lt;/code&gt; is equivalent to the
function &lt;code class=&quot;highlighter-rouge&quot;&gt;mu4e-compose-goto-top&lt;/code&gt; defined above except it is
shorter. The macro &lt;code class=&quot;highlighter-rouge&quot;&gt;beginend--double-tap-begin&lt;/code&gt; implements double-tap
in a way independent of the kind of buffer being visited. The code
handling dired buffers used the same macro.&lt;/p&gt;
&lt;p&gt;I released version 1 of the project.&lt;/p&gt;
&lt;h2 id=&quot;matus-blog-post-and-beginend-on-steroids&quot;&gt;Matus blog post and beginend on steroids&lt;/h2&gt;
&lt;p&gt;The project did not change for the next two years even though I was
using it extensively. One day, I read Matus’ &lt;a href=&quot;https://fuco1.github.io/2017-05-06-Enhanced-beginning--and-end-of-buffer-in-special-mode-buffers-(dired-etc.).html&quot;&gt;blog post&lt;/a&gt; titled:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Enhanced beginning- and end-of-buffer in special mode buffers (dired
etc.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This gave me energy to work on the package again. With Matus, we
released version 2 featuring many changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User visible:
&lt;ul&gt;
&lt;li&gt;Add missing space to the mode lighter&lt;/li&gt;
&lt;li&gt;Add support for many major modes (&lt;a href=&quot;https://magit.vc/&quot;&gt;magit-status&lt;/a&gt;, prog, occur,
&lt;a href=&quot;http://orgmode.org/&quot;&gt;org-agenda&lt;/a&gt;, compilation, &lt;a href=&quot;https://notmuchmail.org/&quot;&gt;notmuch-search&lt;/a&gt;, &lt;a href=&quot;https://github.com/skeeto/elfeed&quot;&gt;elfeed&lt;/a&gt;, &lt;a href=&quot;https://github.com/rejeep/prodigy.el&quot;&gt;prodigy&lt;/a&gt;, …)&lt;/li&gt;
&lt;li&gt;Add a global minor mode&lt;/li&gt;
&lt;li&gt;Push mark when beginend moves point&lt;/li&gt;
&lt;li&gt;Make sure beginend is reasonable when buffer is narrowed&lt;/li&gt;
&lt;li&gt;Update &lt;a href=&quot;https://github.com/DamienCassou/beginend/blob/master/README.org&quot;&gt;README&lt;/a&gt; and include screencasts&lt;/li&gt;
&lt;li&gt;Make the end position coherent across modes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Build process:
&lt;ul&gt;
&lt;li&gt;Add Emacs-25.2 as build target&lt;/li&gt;
&lt;li&gt;Remove compiler warnings&lt;/li&gt;
&lt;li&gt;Add automated linting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Implementation:
&lt;ul&gt;
&lt;li&gt;Factor out common code into new macro making it easy to support
more modes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Testing:
&lt;ul&gt;
&lt;li&gt;84% of the code base is now covered by tests&lt;/li&gt;
&lt;li&gt;Convert tests to buttercup&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding support for a new mode is a matter of a few lines of code
now. Here is how beginend supports going to the meaningful beginning and
end of message buffers now:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beginend-define-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;message-mode&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message-goto-body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;re-search-backward&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;^-- $&quot;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beginend--goto-nonwhitespace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The first &lt;code class=&quot;highlighter-rouge&quot;&gt;progn&lt;/code&gt; specifies how to go to the meaningful beginning
(i.e., after message headers) and the second one specifies how to go
to the meaningful end (i.e., before the signature). These six lines of
code also support double-tap, bind &lt;code class=&quot;highlighter-rouge&quot;&gt;M-&amp;lt;&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;M-&amp;gt;&lt;/code&gt;, take care of
buffer narrowing and set the mark appropriately.&lt;/p&gt;
&lt;p&gt;Here are some screencasts demonstrating the behavior of beginend in
some major modes.&lt;/p&gt;
&lt;h3 id=&quot;dired-mode&quot;&gt;Dired mode&lt;/h3&gt;
&lt;p&gt;The following shows how beginend reacts in dired mode when
dired-hide-details or dired-omit is activated.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/beginend-dired-mode.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;message-mode&quot;&gt;Message mode&lt;/h3&gt;
&lt;p&gt;This screencast shows how beginend allows ignoring both a message
headers and signature.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/beginend-message-mode.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;programming-mode&quot;&gt;Programming mode&lt;/h3&gt;
&lt;p&gt;This shows how beginend moves point at start and end of the code block
in programming buffers, ignoring comments and blank lines.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/beginend-prog-mode.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I hope you enjoy using beginend as much as I enjoyed writing it.&lt;/p&gt;</content><author><name>Damien Cassou</name></author><summary type="html">Thank you Nicolas for letting me borrow (again) your blog to talk about my work. This time, this will not only be my work, but the one of Matus Goljer too (aka Fuco1). Let me present beginend.</summary></entry><entry><title type="html">Indium 0.7 is out!</title><link href="https://emacs.cafe/indium/emacs/javascript/2017/07/24/indium-0.7-released.html" rel="alternate" type="text/html" title="Indium 0.7 is out!" /><published>2017-07-24T13:40:00+02:00</published><updated>2017-07-24T13:40:00+02:00</updated><id>https://emacs.cafe/indium/emacs/javascript/2017/07/24/indium-0.7-released</id><content type="html" xml:base="https://emacs.cafe/indium/emacs/javascript/2017/07/24/indium-0.7-released.html">&lt;p&gt;&lt;a href=&quot;https://github.com/NicolasPetton/Indium&quot;&gt;Indium&lt;/a&gt; – the JavaScript development
environment for Emacs – version 0.7 was released a few days ago!&lt;/p&gt;
&lt;p&gt;This release brings a major improvement: support for source maps (see
the
&lt;a href=&quot;http://indium.readthedocs.io/en/latest/debugger.html#using-sourcemaps&quot;&gt;documentation&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/&quot;&gt;Source maps&lt;/a&gt; make
it possible to us a source JavaScript file (not built/minified) while a minified
file is served. Indium supports source maps both for debugging and setting
breakpoints.&lt;/p&gt;
&lt;p&gt;Installation and update instructions can be found in
the &lt;a href=&quot;https://indium.readthedocs.io/en/latest/&quot;&gt;documentation&lt;/a&gt;. You can also
check out the project on &lt;a href=&quot;https://github.com/NicolasPetton/Indium&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content><author><name>Nicolas Petton</name></author><summary type="html">Indium – the JavaScript development environment for Emacs – version 0.7 was released a few days ago!</summary></entry><entry><title type="html">Orgmode for GTD</title><link href="https://emacs.cafe/emacs/orgmode/gtd/2017/06/30/orgmode-gtd.html" rel="alternate" type="text/html" title="Orgmode for GTD" /><published>2017-06-30T19:00:00+02:00</published><updated>2017-06-30T19:00:00+02:00</updated><id>https://emacs.cafe/emacs/orgmode/gtd/2017/06/30/orgmode-gtd</id><content type="html" xml:base="https://emacs.cafe/emacs/orgmode/gtd/2017/06/30/orgmode-gtd.html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I’ve been using &lt;a href=&quot;http://orgmode.org/&quot;&gt;Orgmode&lt;/a&gt; to implement
the &lt;a href=&quot;https://en.wikipedia.org/wiki/Getting_Things_Done&quot;&gt;GTD methodology&lt;/a&gt; for the
last 4 years.&lt;/p&gt;
&lt;p&gt;Rather than explaining the GTD methodology itself or how Orgmode works, in this
post I’ll detail how I use Orgmode to implement GTD.&lt;/p&gt;
&lt;p&gt;If you don’t know Orgmode and are curious about it, you should head
to &lt;a href=&quot;http://orgmode.org/&quot;&gt;its website&lt;/a&gt; first.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;After 4 years of using &lt;a href=&quot;https://twitter.com/hashtag/gtd?src=hash&quot;&gt;#gtd&lt;/a&gt; daily with &lt;a href=&quot;https://twitter.com/hashtag/orgmode?src=hash&quot;&gt;#orgmode&lt;/a&gt;, I now have 39,175 lines of orgmode in 4 files + archives. &lt;a href=&quot;https://twitter.com/hashtag/emacs?src=hash&quot;&gt;#emacs&lt;/a&gt;&lt;/p&gt;&amp;mdash; Nicolas Petton (@NicolasPetton) &lt;a href=&quot;https://twitter.com/NicolasPetton/status/879673555616714752&quot;&gt;June 27, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;the-orgmode-files&quot;&gt;The orgmode files&lt;/h2&gt;
&lt;p&gt;I split my GTD in four separate files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;inbox.org&lt;/code&gt;: where I collect everything;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;gtd.org&lt;/code&gt;: where I put all my projects;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;someday.org&lt;/code&gt;: All inactive tasks that I might do at some point in the future,
but don’t want to see all the time;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tickler.org&lt;/code&gt;: I put entries in this file with
a &lt;a href=&quot;http://orgmode.org/manual/Timestamps.html&quot;&gt;timestamp&lt;/a&gt; to get reminded at
the right moment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s important to add these files to the agenda file (more on the agenda later),
like the following:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/gtd/inbox.org&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;~/gtd/gtd.org&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;~/gtd/tickler.org&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&quot;1-the-gtd-inbox&quot;&gt;1. The GTD inbox&lt;/h2&gt;
&lt;p&gt;One of the most important aspects of GTD is the inbox. Every thought should be
collected there, and processed later on.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/GTDcanonical.png/1280px-GTDcanonical.png&quot; alt=&quot;inbox&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Orgmode has a great feature that fits really well with this
concept: &lt;a href=&quot;http://orgmode.org/manual/Capture.html&quot;&gt;org-capture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Capturing a thought is one key press away: simply Press &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c c&lt;/code&gt;, and a capture
popup will appear in Emacs. Once you’re done capturing, &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-c&lt;/code&gt; and it will
get stored in the inbox.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/gtd-capture.png&quot; alt=&quot;capture&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here’s how I set it up:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-capture-templates&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;t&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Todo [inbox]&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;entry&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;file+headline&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;~/gtd/inbox.org&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tasks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;* TODO %i%?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;T&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tickler&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;entry&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;file+headline&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;~/gtd/tickler.org&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tickler&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;* %i%? \n %U&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The syntax of capture templates is
explained
&lt;a href=&quot;http://orgmode.org/manual/Capture-templates.html#Capture-templates&quot;&gt;here&lt;/a&gt;. It
offers lots of customization options.&lt;/p&gt;
&lt;p&gt;I press &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c c t&lt;/code&gt; to add an entry to my inbox, and &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c c T&lt;/code&gt; to add an entry to
the tickler (more on that later).&lt;/p&gt;
&lt;p&gt;Here’s how my inbox looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/gtd-inbox.png&quot; alt=&quot;inbox&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My inbox is then processed and emptied daily. When processing the inbox,
I &lt;a href=&quot;http://orgmode.org/manual/Refile-and-copy.html#Refile-and-copy&quot;&gt;refile&lt;/a&gt; each
entry that is actionable and belongs to a project using &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-w&lt;/code&gt;, moving the
entry to the appropriate place. If need be, I create a new project out of it.&lt;/p&gt;
&lt;p&gt;I have set up the refile targets as follows:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-refile-targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/gtd/gtd.org&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:maxlevel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/gtd/someday.org&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:level&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/gtd/tickler.org&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:maxlevel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So that &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-w&lt;/code&gt; prompts me either for a project, the tickler, or someday/maybe
list.&lt;/p&gt;
&lt;h2 id=&quot;2-the-projects-file&quot;&gt;2. The projects file&lt;/h2&gt;
&lt;p&gt;My main file is &lt;code class=&quot;highlighter-rouge&quot;&gt;gtd.org&lt;/code&gt;. That’s where I keep all my active projects. I usually
have around 30 active projects at the same time.&lt;/p&gt;
&lt;p&gt;Each project contains actions to be performed. The first action of each project
is called its “next action”, and that’s always the one I will do when working on
a project. Once a task is done, I mark it as such using the &lt;code class=&quot;highlighter-rouge&quot;&gt;DONE&lt;/code&gt; todo keyword.&lt;/p&gt;
&lt;p&gt;Here’s an example project:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/gtd-project-example.png&quot; alt=&quot;project example&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The completion percentage you see on the screenshot
is &lt;a href=&quot;http://orgmode.org/manual/Checkboxes.html&quot;&gt;yet another neat feature&lt;/a&gt; of
Orgmode :)&lt;/p&gt;
&lt;h3 id=&quot;tags&quot;&gt;Tags&lt;/h3&gt;
&lt;p&gt;Tagging is done using &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-c&lt;/code&gt; on a headline, whether it’s a project or
action. I use tags for several purposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Regular categories, like &lt;code class=&quot;highlighter-rouge&quot;&gt;:emacs:&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;:writing:&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Tags that link to people, like &lt;code class=&quot;highlighter-rouge&quot;&gt;:daniel:&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;GTD contexts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GTD contexts are just regular tags, starting with &lt;code class=&quot;highlighter-rouge&quot;&gt;@&lt;/code&gt;. I make heavy use of them
in
&lt;a href=&quot;http://orgmode.org/worg/org-tutorials/org-custom-agenda-commands.html&quot;&gt;custom Org Agenda commands&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My contexts tend to change over time, but I always have at least &lt;code class=&quot;highlighter-rouge&quot;&gt;@home&lt;/code&gt;,
&lt;code class=&quot;highlighter-rouge&quot;&gt;@office&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;@travelling&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;@phone&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;@email&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;@errands&lt;/code&gt; to filter out next
actions based on my current location for instance.&lt;/p&gt;
&lt;h3 id=&quot;todo-keywords&quot;&gt;TODO keywords&lt;/h3&gt;
&lt;p&gt;I put a todo keyword in all project entries. I think I use fairly regular todo
keywords: &lt;code class=&quot;highlighter-rouge&quot;&gt;TODO&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;WAITING&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;DONE&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;CANCELLED&lt;/code&gt; mostly. The first two for
are used for incomplete states, and the last two for completed states.&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-todo-keywords&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;sequence&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TODO(t)&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;WAITING(w)&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;|&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DONE(d)&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;CANCELLED(c)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;When on a headline, press &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-t&lt;/code&gt; to set the TODO keyword.&lt;/p&gt;
&lt;h3 id=&quot;timestamps-scheduling--deadlines&quot;&gt;Timestamps, scheduling &amp;amp; deadlines&lt;/h3&gt;
&lt;p&gt;I tend to avoid using timestamps in my projects as much as possible. The reason
is simple: unless an entry is an appointment (to the dentist for instance) or
has a fixed deadline (a release scheduled with a customer), I should decide what
to work on depending on the current context (among other things). This also
keeps my agenda clean, free of any fake or self-imposed deadline or schedule.&lt;/p&gt;
&lt;p&gt;But scheduling sometimes makes sense. To do that, press &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-s&lt;/code&gt; on an entry,
and enter the date and/or time. To add a deadline, press &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-d&lt;/code&gt;. Note that
Orgmode is quite smart about how you can enter a date, if you don’t know about
it, refer to
the &lt;a href=&quot;http://orgmode.org/manual/Deadlines-and-scheduling.html&quot;&gt;manual entry&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;filtering-projects--actions&quot;&gt;Filtering projects &amp;amp; actions&lt;/h3&gt;
&lt;p&gt;When deciding what to work on, I use
either &lt;a href=&quot;http://orgmode.org/manual/Sparse-trees.html&quot;&gt;sparse trees&lt;/a&gt; – which
makes it easy to filter the content of my GTD projects by tag, search term,
etc., or I
use
&lt;a href=&quot;http://orgmode.org/worg/org-tutorials/org-custom-agenda-commands.html&quot;&gt;custom agenda commands&lt;/a&gt;. When
discovering Orgmode, most people think that its agenda is just a regular
agenda. Sure, it does daily/weekly agendas, but it offers much more than
that. Quoting the manual:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Org-mode’s built-in agenda commands are powerful tools for searching your
notes and for gathering, sorting, filtering, and displaying your tasks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I use custom agenda commands mostly to get an overview of actions by context or
tag. Here’s an example custom agenda command that will display all actions for
the &lt;code class=&quot;highlighter-rouge&quot;&gt;@office&lt;/code&gt; context:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-custom-commands&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;o&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;At the office&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tags-todo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@office&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-agenda-overriding-header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Office&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Following the GTD principle, what I usually want is to only show the &lt;em&gt;first
action to be done&lt;/em&gt; (or next action) for each project with the &lt;code class=&quot;highlighter-rouge&quot;&gt;@office&lt;/code&gt; tag.&lt;/p&gt;
&lt;p&gt;That can be achieved using a skipping condition:&lt;/p&gt;
&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-agenda-custom-commands&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;o&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;At the office&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tags-todo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@office&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-agenda-overriding-header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Office&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-agenda-skip-function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-org-agenda-skip-all-siblings-but-first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-org-agenda-skip-all-siblings-but-first&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Skip all but the first non-done entry.&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;should-skip-entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-current-is-todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;should-skip-entry&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;save-excursion&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;should-skip-entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-goto-sibling&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-current-is-todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;should-skip-entry&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;should-skip-entry&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;outline-next-heading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;goto-char&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-current-is-todo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TODO&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-get-todo-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Creating custom agenda commands can be a bit tricky at first, one easy way is to
customize them via &lt;code class=&quot;highlighter-rouge&quot;&gt;M-x customize-variable RET org-agenda-custom-commands&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To select an agenda command to execute, press &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c a&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;3-the-somedaymaybe-list&quot;&gt;3. The “Someday/Maybe” list&lt;/h2&gt;
&lt;p&gt;Did you notice that &lt;code class=&quot;highlighter-rouge&quot;&gt;someday.org&lt;/code&gt; is not part of the agenda files set in
&lt;code class=&quot;highlighter-rouge&quot;&gt;org-agenda-files&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;That’s because I do not want to see any entry from this file appearing in my
agenda buffers, unless I’m doing my weekly review. That’s exactly the purpose of
the “Someday/Maybe” list.&lt;/p&gt;
&lt;p&gt;This file should be reviewed once a week as part of the weekly review (which I
do this on Sunday evenings).&lt;/p&gt;
&lt;p&gt;During each weekly review, I move projects back and forth between the “active”
state (in &lt;code class=&quot;highlighter-rouge&quot;&gt;gtd.org&lt;/code&gt;) and “later” state (in &lt;code class=&quot;highlighter-rouge&quot;&gt;someday.org&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;For instance, if a project has moved forward to a certain point, but I know that
it will stall for a few weeks for some reason, I move it to
&lt;code class=&quot;highlighter-rouge&quot;&gt;someday.org&lt;/code&gt;. During a later weekly review, I’ll move it back to &lt;code class=&quot;highlighter-rouge&quot;&gt;gtd.org&lt;/code&gt; when
it will become active again.&lt;/p&gt;
&lt;p&gt;To move projects around, I also use refiling.&lt;/p&gt;
&lt;h2 id=&quot;4-the-tickler&quot;&gt;4. The tickler&lt;/h2&gt;
&lt;p&gt;The tickler is one of the best concepts of GTD in my opinion.&lt;/p&gt;
&lt;p&gt;Let’s say you will have to pay a bill in a month. You need to write it down in
your GTD if you don’t want to miss the deadline. But you also don’t want to be
reminded of that each and every time you browse through your GTD projects: now
is not the time to pay it.&lt;/p&gt;
&lt;p&gt;That’s where the tickler kicks in: Add an entry to your tickler file with a
timestamp, and forget about it!&lt;/p&gt;
&lt;p&gt;When time will come, the action will appear in your Org Agenda, reminding you of
the bill you have to pay, and all you will have to do is moving it to your
inbox. Until then, you can just focus on something else and free your mind from
this task.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;All reference documents are put in a &lt;code class=&quot;highlighter-rouge&quot;&gt;references&lt;/code&gt; folder next to my Orgmode
files. They are then linked (using &lt;code class=&quot;highlighter-rouge&quot;&gt;org-store-link&lt;/code&gt;) from Dired buffers into my
projects for quick access.&lt;/p&gt;
&lt;p&gt;I also link emails (which I happen to read within Emacs) using &lt;code class=&quot;highlighter-rouge&quot;&gt;org-store-link&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;archiving&quot;&gt;Archiving&lt;/h2&gt;
&lt;p&gt;During my weekly reviews, I archive done projects using &lt;code class=&quot;highlighter-rouge&quot;&gt;C-c C-x C-a&lt;/code&gt;
(&lt;code class=&quot;highlighter-rouge&quot;&gt;org-archive-subtree-default&lt;/code&gt;), which moved the entry at point to an archive
file.&lt;/p&gt;
&lt;p&gt;This way my GTD files remain uncluttered and I never delete any data.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is a very wide topic, so obviously I haven’t covered everything, but I hope
that explains the basics of how I use Orgmode to implement GTD.&lt;/p&gt;
&lt;p&gt;This is really only my way of doing it. Orgmode is such a moldable tool that I
don’t think that there are 2 exactly identical setups.&lt;/p&gt;</content><author><name>Nicolas Petton</name></author><summary type="html">Introduction</summary></entry><entry><title type="html">Hierarchy.el</title><link href="https://emacs.cafe/emacs/guest-post/2017/06/26/hierarchy.html" rel="alternate" type="text/html" title="Hierarchy.el" /><published>2017-06-26T21:00:00+02:00</published><updated>2017-06-26T21:00:00+02:00</updated><id>https://emacs.cafe/emacs/guest-post/2017/06/26/hierarchy</id><content type="html" xml:base="https://emacs.cafe/emacs/guest-post/2017/06/26/hierarchy.html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Thank you Nicolas for letting me borrow your blog to talk about my
work.&lt;/p&gt;
&lt;p&gt;I would like to present &lt;a href=&quot;https://github.com/DamienCassou/hierarchy&quot;&gt;hierarchy&lt;/a&gt;, an Emacs library to create, query,
navigate and display hierarchies. This library can be used to
manipulate &lt;em&gt;any&lt;/em&gt; kind of hierarchy. For example, a developer can use
it with file hierarchies (see the &lt;a href=&quot;https://github.com/DamienCassou/hierarchy/tree/master/examples&quot;&gt;file-system example&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/files-tree-anime.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;JSON documents (see the &lt;a href=&quot;https://github.com/DamienCassou/json-navigator&quot;&gt;json-navigator&lt;/a&gt; project),&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/json-tree-anime.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;or class hierarchies (see the &lt;a href=&quot;https://github.com/DamienCassou/klassified.el&quot;&gt;klassified&lt;/a&gt; prototype project)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/klassified-tabulated-anime.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As you can see, there are multiple ways to display a given hierarchy:
as a tree widget (as shown above for the file hierarchy and JSON
document), as a tabulated list (as shown above for the class
hierarchy) or as plain text as shown below:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;animal
bird
dove
pigeon
cow
dolphin
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A &lt;em&gt;hierarchy&lt;/em&gt; is a set of items with a parent-child relationship. A
hierarchy has at least one &lt;em&gt;root&lt;/em&gt;, an item with no parent, and can
have more than one (contrary to a tree which has one and only one
root). An &lt;em&gt;item&lt;/em&gt; of a hierarchy can be anything distinguishable
with the &lt;code class=&quot;highlighter-rouge&quot;&gt;equal&lt;/code&gt; function. &lt;em&gt;Siblings&lt;/em&gt; are items with the same
parent.&lt;/p&gt;
&lt;p&gt;In the following we explore some parts of the library’s API so you can
start using it in your own project right away.&lt;/p&gt;
&lt;h2 id=&quot;creation&quot;&gt;Creation&lt;/h2&gt;
&lt;p&gt;There are two main ways to create a new hierarchy: either through
functions describing the parent-child relationship or through a nested
list.&lt;/p&gt;
&lt;h3 id=&quot;creation-from-functions&quot;&gt;Creation from functions&lt;/h3&gt;
&lt;p&gt;To create a hierarchy from functions, you can write something like
that:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'hierarchy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;parentfn&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Given an item, return its parent&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cl-case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'bird&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'bird&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-add-tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'dove&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;parentfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-add-tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'pigeon&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;parentfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-add-tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'dolphin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;parentfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-add-tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'cow&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;parentfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-sort&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;;; sort siblings with #'string&amp;lt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This creates the animal hierarchy shown above. The
&lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-add-tree&lt;/code&gt; function takes a hierarchy to add to as first
parameter, then an item to add and then a function to get the
parent of the item (and the parent of the parent, recursively). This
creates a hierarchy bottom-up.&lt;/p&gt;
&lt;p&gt;It is also possible to create a hierarchy top-down by passing a fourth
argument to &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-add-tree&lt;/code&gt; in this way:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;childrenfn&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Given an item, return its children&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cl-case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-add-tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals2&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'animal&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;childrenfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-sort&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At this point, &lt;code class=&quot;highlighter-rouge&quot;&gt;animals&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;animals2&lt;/code&gt; represent the same hierarchy
as can be verified with &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-equal&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-equal&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;The two hierarchies are equal&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;The two hierarchies are not equal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;two&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;hierarchies&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;are&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;equal&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3 id=&quot;creation-from-a-nested-list&quot;&gt;Creation from a nested list&lt;/h3&gt;
&lt;p&gt;The second way to build a hierarchy is to start from a nested
list:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals3&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-from-list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In this case, the nodes in the resulting hierarchy are not symbols as
in &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy2&lt;/code&gt; above, but sub-lists:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with-temp-buffer&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;buffer-substring-no-properties&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Each line of the text above shows an item indented depending on its
depth in the hierarchy (i.e., the number of parents before reaching a
root).&lt;/p&gt;
&lt;p&gt;You can pass an optional argument to &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-print&lt;/code&gt; if you want to
only print the &lt;code class=&quot;highlighter-rouge&quot;&gt;car&lt;/code&gt; of each sub-list:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with-temp-buffer&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;symbol-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;buffer-substring-no-properties&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;animal
dolphin
cow
bird
pigeon
dove
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It is also possible to create a new hierarchy from an existing
one. For example, to create a hierarchy from &lt;code class=&quot;highlighter-rouge&quot;&gt;animals3&lt;/code&gt; that looks
like &lt;code class=&quot;highlighter-rouge&quot;&gt;animals&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;animals2&lt;/code&gt; :&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animals3-new&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-map-hierarchy&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;animals3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-equal&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals3-new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;The two hierarchies are equal&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;The two hierarchies are not equal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;two&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;hierarchies&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;are&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;equal&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-map-hierarchy&lt;/code&gt; function takes a transformation function
as first argument and a source hierarchy as second one. The
transformation function will receive an item and its indentation level
in the source hierarchy and must produce an item for the resulting
hierarchy.&lt;/p&gt;
&lt;h2 id=&quot;querying&quot;&gt;Querying&lt;/h2&gt;
&lt;p&gt;The hierarchy API provides its fair share of functions to query a
hierarchy.&lt;/p&gt;
&lt;p&gt;The functions &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-items&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-roots&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-leafs&lt;/code&gt; return lists of items in the hierarchy. The first
function returns all items, the second one only returns items with no
parent and the third one returns items with no children:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-items&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-roots&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-leafs&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;There are also some predicate functions (returning a boolean) such as
&lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-has-item&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-empty-p&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-equal&lt;/code&gt;,
&lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-child-p&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-descendant-p&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;navigation&quot;&gt;Navigation&lt;/h2&gt;
&lt;p&gt;There are several ways to iterate over items of a hierarchy. The
simplest function is &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-map&lt;/code&gt; which returns a list of the
result of applying a function to each item. For example, to get a
list of items and their depths in the hierarchy, you can write:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-map&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This function walks the hierarchy from the roots to the leafs. It is
also possible to walk the hierarchy from the leafs to a root using
&lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-map-tree&lt;/code&gt;. As additional bonus, the result of applying the
function to children of an item is passed as a parameter when the
function is called on the item itself:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-map-tree&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;animal&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bird&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dove&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pigeon&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cow&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dolphin&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We have already seen the function &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-map-hierarchy&lt;/code&gt; that
builds and returns a hierarchy from an existing one by applying a
function on each item (just like &lt;code class=&quot;highlighter-rouge&quot;&gt;mapcar&lt;/code&gt; does it for lists).&lt;/p&gt;
&lt;h2 id=&quot;display&quot;&gt;Display&lt;/h2&gt;
&lt;p&gt;Finally, hierarchies can be displayed in many different ways. We have
already seen &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-print&lt;/code&gt; which formats a hierarchy as text in
the current buffer. The functions &lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-tabulated-display&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;hierarchy-tree-display&lt;/code&gt; are respectively responsible for displaying a
hierarchy as a list of elements and as a tree (as can be seen in the
beginning of this article). For example, to display our hierarchy of
animals:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;switch-to-buffer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-tabulated-display&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;symbol-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;img src=&quot;/img/animals-tabulated-static.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The functions responsible for displaying a hierarchy take a function
as parameter whose name is &lt;code class=&quot;highlighter-rouge&quot;&gt;labelfn&lt;/code&gt;. This name indicates that the
function should take two parameters (an item of a hierarchy and an
indentation level) and insert some text in the current buffer. The
hierarchy API provides several functions to help you build a &lt;code class=&quot;highlighter-rouge&quot;&gt;labelfn&lt;/code&gt;
function. For example, if you want your animal hierarchy printed with
indentation and clickable labels, you can write something like that:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;switch-to-buffer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-tabulated-display&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-labelfn-indent&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hierarchy-labelfn-button&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;symbol-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;You clicked on: %s&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;img src=&quot;/img/animals-tabulated-anime.gif&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The hierarchy library features an easy to use API to create, query,
navigate and display any kind of hierarchy. This library has already
been used to display hierarchies of files and classes as well as to
navigate JSON structures. All functions are well documented and
tested.&lt;/p&gt;
&lt;p&gt;Have fun playing with the library.&lt;/p&gt;</content><author><name>Damien Cassou</name></author><summary type="html">Introduction</summary></entry><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">&lt;p&gt;&lt;a href=&quot;https://github.com/NicolasPetton/Indium&quot;&gt;Indium&lt;/a&gt; – the JavaScript development
environment for Emacs – version 0.6 has just been released!&lt;/p&gt;
&lt;p&gt;This release brings a lot of improvements and polish:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The stepping debugger now shows exceptions inline in the source;&lt;/li&gt;
&lt;li&gt;Breakpoints can now be &lt;a href=&quot;https://indium.readthedocs.io/en/latest/&quot;&gt;activated and deactivated&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Indium supports &lt;a href=&quot;https://indium.readthedocs.io/en/latest/code-evaluation.html#adding-and-removing-breakpoints&quot;&gt;live code updates&lt;/a&gt; (hot-swapping JavaScript);&lt;/li&gt;
&lt;li&gt;NodeJS integration has been &lt;a href=&quot;https://indium.readthedocs.io/en/latest/setup.html#nodejs&quot;&gt;greatly improved&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Installation and update instructions can be found in
the &lt;a href=&quot;https://indium.readthedocs.io/en/latest/&quot;&gt;documentation&lt;/a&gt;. You can also check out the project on &lt;a href=&quot;https://github.com/NicolasPetton/Indium&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href=&quot;https://github.com/TatriX&quot;&gt;Tatrix&lt;/a&gt; for his contributions to this release!&lt;/p&gt;</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">&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;I’m working on a fairly large JavaScript code base for which maintenance can
sometimes be an issue.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2 id=&quot;what-do-we-already-have&quot;&gt;What do we already have?&lt;/h2&gt;
&lt;p&gt;Let’s see what building blocks are already available.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nicolaspetton/xref-js2&quot;&gt;xref-js2&lt;/a&gt; makes it easy to find all
references to a specific function within a project,
and &lt;a href=&quot;https://github.com/mooz/js2-mode&quot;&gt;js2-mode&lt;/a&gt; exposes an AST that can be
visited.&lt;/p&gt;
&lt;p&gt;All in all, what I want to achieve shouldn’t be too hard to implement!&lt;/p&gt;
&lt;h2 id=&quot;first-steps&quot;&gt;First steps&lt;/h2&gt;
&lt;p&gt;I’m calling my small package &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-unused&lt;/code&gt;, so all functions and variables will
have that prefix.&lt;/p&gt;
&lt;p&gt;We’ll need some packages along the way, so let’s require them:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'xref-js2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'subr-x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The first step is to find all function definitions within the current buffer.
&lt;code class=&quot;highlighter-rouge&quot;&gt;JS2-mode&lt;/code&gt; has a function &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-visit-ast&lt;/code&gt; that makes it really easy to traverse
the entire AST tree.&lt;/p&gt;
&lt;p&gt;We can first define a variable that will hold all function definition names that
we find:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused-definitions&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now let’s traverse the AST and find all function definitions. We want to find:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;all assignments that assign to a function;&lt;/li&gt;
&lt;li&gt;all function declarations that are named (skipping anonymous functions).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused--find-definitions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Reset the value before visiting the AST&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused-definitions&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-visit-ast&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-mode-ast&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-unused-visitor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused-visitor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end-p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Add NODE's name to `js2-unused-definitions` if it is a function.&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end-p&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cond&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; assignment to a function&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-assign-node-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-function-node-p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-assign-node-right&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-node-string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-assign-node-left&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused-definitions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; function declaration (skipping anonymous ones)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-function-node-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;if-let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-function-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused-definitions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&quot;finding-references-using-xref-js2&quot;&gt;Finding references using xref-js2&lt;/h2&gt;
&lt;p&gt;Now that we can find and store all function names in a list, let’s use
&lt;code class=&quot;highlighter-rouge&quot;&gt;xref-js2&lt;/code&gt; to filter the ones that are never referenced. If we find
unreferenced functions, we simply display a message listing them.&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused-functions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Make sure that JS2 has finished parsing the buffer&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-mode-wait-for-parse&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Walk the AST tree to find all function definitions&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-unused--find-definitions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Use xref-js2 to filter the ones that are not referenced anywhere&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;unused&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seq-filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xref-js2--find-references&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-unused--unqualified-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;js2-unused-definitions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; If there are unreferenced function, display a message&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;unused&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unused functions in %s: %s &quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;file-name-nondirectory&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;buffer-file-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mapconcat&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;unused&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;No unused function found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-unused--unqualified-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&quot;Return the local name of NAME.
foo.bar.baz =&amp;gt; baz&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;save-match-data&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string-match&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;\\.\\([^.]+\\)$&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;match-string&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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 &lt;code class=&quot;highlighter-rouge&quot;&gt;emacs.d&lt;/code&gt;, or make a proper package out of
it.&lt;/p&gt;
&lt;p&gt;If you find this feature useful, you can grab it from
my
&lt;a href=&quot;https://gitlab.petton.fr/nico/emacs.d/blob/master/local-packages/js2-unused.el&quot;&gt;emacs.d&lt;/a&gt;.&lt;/p&gt;</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">&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;If you haven’t read it yet, you should jump to
the &lt;a href=&quot;/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html&quot;&gt;first post&lt;/a&gt;
first to get things started.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-tern--company-mode-for-auto-completion&quot;&gt;Setting up Tern &amp;amp; company-mode for auto-completion&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ternjs.net&quot;&gt;Tern&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;Unfortunately, cross-references with tern never reliably worked for me, that’s
why I have always been
using &lt;a href=&quot;https://github.com/nicolaspetton/xref-js2&quot;&gt;xref-js2&lt;/a&gt; instead for that
(see &lt;a href=&quot;/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html&quot;&gt;part #1&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;For auto-completion, we’ll be using company-mode with tern. Let’s go ahead and
install tern:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo npm install -g tern
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now let’s install the Emacs packages:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;M-x package-install RET company-tern RET
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The Emacs configuration is straight-forward, we simply enable company-mode with
the tern backend for JavaScript buffers:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'company&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'company-tern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'company-backends&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'company-tern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'js2-mode-hook&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tern-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;company-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Disable completion keybindings, as we use xref-js2 instead&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tern-mode-keymap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tern-mode-keymap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;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 &lt;code class=&quot;highlighter-rouge&quot;&gt;.tern-project&lt;/code&gt; placed in the
root folder containing your JavaScript files.&lt;/p&gt;
&lt;p&gt;Here’s an example setup for a project that uses &lt;code class=&quot;highlighter-rouge&quot;&gt;requirejs&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;jQuery&lt;/code&gt;,
ignoring files from the &lt;code class=&quot;highlighter-rouge&quot;&gt;bower_components&lt;/code&gt; directory:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;libs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jquery&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;loadEagerly&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./**/*.js&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;dontLoad&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./bower_components/&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;requirejs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;baseURL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once setup, tern offers superb completion. Together with company-mode, you get
great context-based completion with type inference.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/tern-company-mode.png&quot; alt=&quot;Ternjs&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When completing a function, you can hit &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;F1&amp;gt;&lt;/code&gt; to get its documentation:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/tern-documentation.png&quot; alt=&quot;Ternjs documentation&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;until-next-time&quot;&gt;Until next time&lt;/h2&gt;
&lt;p&gt;In the next articles I’ll cover linting with Flycheck, &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;grunt&lt;/code&gt;
integration into Emacs, and of course how to setup and
use &lt;a href=&quot;https://indium.readthedocs.io&quot;&gt;Indium&lt;/a&gt;.&lt;/p&gt;</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">&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;In this first article we’ll see how to
setup &lt;a href=&quot;https://github.com/mooz/js2-mode&quot;&gt;js2-mode&lt;/a&gt; and two other packages that
rely upon it: &lt;a href=&quot;https://github.com/magnars/js2-refactor.el&quot;&gt;js2-refactor&lt;/a&gt;
and &lt;a href=&quot;https://github.com/nicolaspetton/xref-js2&quot;&gt;xref-js2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Emacs comes with a major mode for JavaScript named &lt;code class=&quot;highlighter-rouge&quot;&gt;js-mode&lt;/code&gt;. While it is a
good major mode, we’ll be using &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-mode&lt;/code&gt; instead, an external package that
extends &lt;code class=&quot;highlighter-rouge&quot;&gt;js-mode&lt;/code&gt; 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.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-js2-mode&quot;&gt;Setting up js2-mode&lt;/h2&gt;
&lt;p&gt;If you haven’t done it already, you should first setup &lt;code class=&quot;highlighter-rouge&quot;&gt;package.el&lt;/code&gt; to
use &lt;a href=&quot;https://melpa.org&quot;&gt;MELPA&lt;/a&gt;, then install and setup &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-mode&lt;/code&gt; like the
following:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;M-x package-install RET js2-mode RET
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'js2-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'auto-mode-alist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\\.js\\'&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Better imenu&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'js2-mode-hook&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-imenu-extras-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&quot;js2-refactor-and-xref-js2&quot;&gt;js2-refactor and xref-js2&lt;/h2&gt;
&lt;p&gt;Now that we’re using &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-mode&lt;/code&gt; for JavaScript buffers, let’s take advantage its
capabilities of and install two other
packages: &lt;a href=&quot;https://github.com/magnars/js2-refactor.el&quot;&gt;js2-refactor&lt;/a&gt;
and &lt;a href=&quot;https://github.com/nicolaspetton/xref-js2&quot;&gt;xref-js2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;js2-refactor&lt;/code&gt; adds powerful refactorings based on the AST generated by
&lt;code class=&quot;highlighter-rouge&quot;&gt;js2-mode&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;xref-js2&lt;/code&gt; makes it easy to jump to function references or
definitions.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;xref-js2&lt;/code&gt; uses &lt;code class=&quot;highlighter-rouge&quot;&gt;ag&lt;/code&gt; to perform searches, so you’ll need to install it as well.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;M-x package-install RET js2-refactor RET
M-x package-install RET xref-js2 RET
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'js2-refactor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'xref-js2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'js2-mode-hook&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2-refactor-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2r-add-keybindings-with-prefix&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C-c C-r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-mode-map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C-k&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2r-kill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; js-mode (which js2 is based on) binds &quot;M-.&quot; which conflicts with xref, so&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; unbind it.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js-mode-map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;M-.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'js2-mode-hook&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'xref-backend-functions&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xref-js2-xref-backend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that everything’s setup, let’s see how to use &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-refactor&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;xref-js2&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;using-js2-refactor&quot;&gt;Using js2-refactor&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;js2-refactor&lt;/code&gt; is a JavaScript refactoring library for emacs.&lt;/p&gt;
&lt;p&gt;It provides a collection of refactoring functions leveraging the AST provided by
&lt;code class=&quot;highlighter-rouge&quot;&gt;js2-mode&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Refactorings go from inlining/extracting variables to converting ternary
operators to if statements.
The &lt;a href=&quot;https://github.com/magnars/js2-refactor.el&quot;&gt;README&lt;/a&gt; provides the full list of
keybindings.&lt;/p&gt;
&lt;p&gt;One minor tweak that I really couldn’t live without is binding &lt;code class=&quot;highlighter-rouge&quot;&gt;js2r-kill&lt;/code&gt; to
&lt;code class=&quot;highlighter-rouge&quot;&gt;C-k&lt;/code&gt; in JS buffers:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-elisp&quot; data-lang=&quot;elisp&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;js2-mode-map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kbd&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C-k&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;js2r-kill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This command is very similar to killing in &lt;code class=&quot;highlighter-rouge&quot;&gt;paredit&lt;/code&gt;: It kills up to the end of
the line, but always keeping the AST valid.&lt;/p&gt;
&lt;p&gt;Here’s a usage example of &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-refactor&lt;/code&gt;: renaming a function parameter and
inlining a variable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/js2-refactorings.gif&quot; alt=&quot;Refactorings&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;using-xref-js2&quot;&gt;Using xref-js2&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;xref-js2&lt;/code&gt; adds support for quickly jumping to function definitions or
references to JavaScript projects in Emacs (&amp;gt;= 25.1).&lt;/p&gt;
&lt;p&gt;Instead of using a tag system, it relies on &lt;code class=&quot;highlighter-rouge&quot;&gt;ag&lt;/code&gt; to query the codebase of a
project.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;M-.&lt;/code&gt; Jump to definition&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;M-?&lt;/code&gt; Jump to references&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;M-,&lt;/code&gt; Pop back to where &lt;code class=&quot;highlighter-rouge&quot;&gt;M-.&lt;/code&gt; was last invoked.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s a usage example of &lt;code class=&quot;highlighter-rouge&quot;&gt;xref-js2&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/xref-jump-to-references.gif&quot; alt=&quot;Jumping to references&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;until-next-time&quot;&gt;Until next time&lt;/h2&gt;
&lt;p&gt;You should now have a decent setup for &lt;code class=&quot;highlighter-rouge&quot;&gt;js2-mode&lt;/code&gt; and associated tools.&lt;/p&gt;
&lt;p&gt;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!&lt;/p&gt;</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></feed>