Indium

Indium is a JavaScript development environment for Emacs.

Indium is Free Software, licensed under the GPL v3.0. You can follow its development on GitHub.

Indium connects to a browser tab or nodejs process and provides several features for JavaScript development, including:

  • a REPL (with auto completion) & object inspection;
  • an inspector, with history and navigation;
  • a scratch buffer (M-x indium-scratch);
  • JavaScript evaluation in JS buffers with indium-interaction-mode;
  • a stepping Debugger, similar to edebug, or cider.

This documentation can be read online at https://indium.readthedocs.io and in Info format (within Emacs with (info "Indium")).

It is also available in Info format and can be consulted from within Emacs with C-h i m indium RET.

Table of contents

Installation

Note

If you already have installed Jade, you should read the Migration from Jade page first.

Indium supports Emacs 25.3+, works with Chrome (debugging protocol v1.2, see Chrome/Chromium requirements) and NodeJS, see NodeJS requirements.

Indium works with js-mode, js2-mode, js2-jsx-mode and rjsx-mode. It supports the ECMAScript features of the runtime it connects to.

Indium is available on MELPA, MELPA Stable.

The Indium server

Indium needs to communicate with a small server for evaluation and debugging. Install the server with the following command (prepend sudo on GNU/Linux):

npm install -g indium

Using MELPA

Unless you are already using MELPA, you will have to setup package.el to use MELPA or MELPA Stable repositories. You can follow this documentation.

You can install Indium with the following command:

M-x package-install [RET] indium [RET]

or by adding this bit of Emacs Lisp code to your Emacs initialization file (.emacs or init.el):

(unless (package-installed-p 'indium)
  (package-install 'indium))

If the installation doesn’t work try refreshing the package list:

M-x package-refresh-contents [RET]

Manual installation

If you want to install Indium manually, make sure to install websocket.el. Obtain the code of Indium from the repository.

Add the following to your Emacs configuration:

;; load Indium from its source code
(add-to-list 'load-path "~/projects/indium")
(require 'indium)

Getting up and running

Project configuration

Place a .indium.json file in the root folder of your JavaScript project. The project file can contain one or many configurations settings for NodeJS (see NodeJS configuration options) and Chrome/Chromium (see Chrome/Chromium configuration options).

Here is a minimalist .indium.json file.:

{
  "configurations": [
    {
      "name": "Web project",
      "type": "chrome"
    }
  ]
}

General configuration

The .indium.json file can contain as many configurations as needed, and mix any supported configuration types.

The currently supported type values are "chrome" and "node".

The root directory of the source files is by default set to the directory where this .indium.json file is placed, but it can be overridden with the root (or the webRoot alias) option:

{
  "configurations": [
    {
      "type": "chrome",
      "root": "src"
    }
  ]
}

Custom sourcemap path overrides can be set with sourceMapPathOverrides. See Using sourcemaps for more information on sourcemaps and debugging.

Chrome/Chromium configuration options

host:Host on which Chrome is running (defaults to "localhost").
port:Port on which Chrome is running (defaults to 9222).
url:Url to open when running indium-launch.

Example configuration:

{
  "configurations": [
    {
      "name": "Web project",
      "type": "chrome",
      "host": "192.168.22.1",
      "url": "http://192.168.22.1/myproject/index.html",
      "port": 9222
    }
  ]
}

NodeJS configuration options

program:Nodejs program to start a new process. The --inspect flag will be added automatically. Expected type: string.
args:Arguments passed to the program to debug. Expected type: string.
inspect-brk:Whether Indium should break at the first statement (false by default).
host:Host on which the Node inspector is listening (defaults to "localhost").
port:Port on which the Node inspector is listening (defaults to 9229).

Here is an example configuration for debugging Gulp tasks:

{
  "configurations": [
    {
      "name": "Gulp",
      "type": "node",
      "program": "node",
      "args": "./node_modules/gulp/bin/gulp.js",
      "inspect-brk": true
    }
  ]
}

When the NodeJS application runs on another computer (or inside a container like Docker), a custom remote project root path can be set with remoteRoot. See Setting a different remote root (NodeJS) for more information on script paths and debugging.

Starting Indium

Indium can be started in two modes:

  • Connect: M-x indium-connect Connect indium to a running runtime from one of the configurations in the .indium.json project file.
  • Launch: M-x indium-launch Start a JavaScript process (Chrome or NodeJS) as specified from the configurations in the .indium.json project file.

NodeJS requirements

Nodejs >= 8.x is required for Indium to work.

If your distribution ships an old version of NodeJS, you can install a more recent version using nvm:

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash

Once nvm is install, you can easily install and use the version of NodeJS you want:

$ nvm install v8
$ nvm alias default v8
$ node --version

If you install NodeJS using nvm, chances are that Emacs won’t have it in its exec path. A simple solution is to use the excellent exec-path-from-shell package.

Chrome/Chromium requirements

Chrome/Chromium >= 60.0 is required for Indium to properly work (debugging protocol v1.2).

When the variable indium-chrome-use-temporary-profile is non-nil (the default), M-x indium-launch will start a new instance of Chrome/Chromium with the remote debugging port set up.

Otherwise, you can start Chrome/Chromium with the --remote-debugging-port flag like the following:

chromium --remote-debugging-port=9222 https://localhost:3000

If you start Chrome manually, make sure that no instance of Chrome is already running, otherwise Chrome will simply open a new tab on the existing Chrome instance, and the remote-debugging-port will not be set.

The REPL

Starting a REPL

A REPL (Read Eval Print Loop) buffer is automatically open when a new Indium connection is made (see Getting up and running).

_images/repl.png

The REPL offers the following features:

  • Auto completion with company-mode
  • JS syntax highlighting
  • Pretty printing and preview of printed values
  • Access to the object inspector (see The inspector)
_images/repl2.png

Using the REPL

Keybindings

Here is the list of available keybindings in a REPL buffer:

Reconnecting from the REPL buffer

When a connection is closed (most probably because other devtools were open on the same runtime), the REPL will display two buttons, one to try to reopen the connection, and another one to kill Emacs buffers using this connection (the REPL buffer, inspectors & debuggers).

Code evaluation & context

When evaluating code in the REPL, Indium will always run the code on the current execution context.

This means that while debugging, code execution will happen in the context of the current stack frame, and will be able to access local variables from the stack, etc.

Interaction in JS buffers

Indium comes with a minor mode called indium-interaction-mode for interactive programming. To enable it in all JavaScript buffers, add something like the following to your Emacs configuration:

(require 'indium)
(add-hook 'js-mode-hook #'indium-interaction-mode)

When indium-interaction-mode is on, you can evaluate code, inspect objects and add or remove breakpoints from your buffers.

Evaluating and inspecting

Here’s a list of available keybindings:

  • C-x C-e: Evaluate the JavaScript expression preceding the point.
  • C-M-x: Evaluate the innermost function enclosing the point.
  • C-c M-i: Inspect the result of the evaluation of an expression (see The inspector).
  • C-c M-:: Prompt for an expression to evaluate and inspect.
  • M-x indium-eval-buffer: Evaluate the entire buffer.
  • M-x indium-eval-region: Evaluate the current region.

Switching to the REPL buffer

Press C-c C-z from any buffer with indium-interaction-mode turned on to switch back to the REPL buffer (see The REPL).

Adding and removing breakpoints

You need to first make sure that Indium is set up correctly to use local files (see General configuration).

  • C-c b b: Add a breakpoint
  • C-c b c: Add a conditional breakpoint
  • C-c b k: Remove a breakpoint
  • C-c b t: Toggle a breakpoint
  • C-c b K: Remove all breakpoints from the current buffer
  • C-c b e: Edit condition of a breakpoint
  • C-c b l: List all breakpoints and easily jump to any breakpoint
  • C-c b d: Deactivate all breakpoints (the runtime won’t pause when hitting a breakpoint)
  • C-c b a: Activate all breakpoints (it has no effect if breakpoints have not been deactivated)

The left fringe or margin can also be clicked to add or remove breakpoints.

Once a breakpoint is set, execution will stop when a breakpoint is hit, and the Indium debugger pops up (see The stepping debugger).

Since Indium 0.7, breakpoints are supported in source files with an associated sourcemap, see Using sourcemaps.

Note

Breakpoints are persistent: if the connection is closed, when a new connection is made Indium will attempt to add back all breakpoints.

The stepping debugger

Using sourcemaps

Since version 0.7, Indium uses sourcemap files by default.

For sourcemaps to work properly with Chrome/Chromium, make sure that a workspace is correctly set (see Getting up and running).

Warning

If your project uses sourcemaps, we advise you to use js-mode with js2-minor-mode instead of js2-mode. js2-mode can be extremely slow at parsing large files (like compiled JavaScript files) that the debugger might open if a stack frame source is not source-mapped. This can happen for instance when using Webpack.

Overriding sourcemap paths

Some sourcemaps cannot be used as is and need path rewriting to map to locations on disks.

Indium provides the configuration option sourceMapPathOverrides for providing custom sourcemap paths.

The default mapping works well for Webpack projects:

{
  "webpack:///./~/": "${root}/node_modules/",
  "webpack:///./":   "${root}/",
  "webpack:///":     "/",
  "webpack:///src/": "${root}/"
}

Overriding the sourceMapPathOverrides option will erase the default mapping.

Tip

If sourcemaps do not seem to work, you can see how Indium resolves sourcemap paths using M-x indium-list-sourcemap-sources.

Setting a different remote root (NodeJS)

When running a NodeJS application on a remote machine or inside a Docker container, your application’s root folder path might not correspond to where their source code is located on your local disk.

In this case, you can tell Indium to replace the root path with a different location using the remoteRoot configuration option.

{
… “remoteRoot”: “/var/task”

}

Note that remoteRoot can be used together with the root configuration option.

Blackboxing scripts

The custom variable indium-debugger-blackbox-regexps holds a list of regular expression of script paths to blackbox when debugging.

Blackboxed scripts are skipped when stepping in the debugger.

The inspector

Indium features an object inspector that can be open on any object reference from a REPL buffer (see The REPL), the debugger (see The stepping debugger), or the result of any evaluation of JavaScript code (see Interaction in JS buffers).

To inspect the result of the evaluation of an expression, press C-c M-i. An inspector buffer will pop up. You can also press RET or left click on object links from the REPL buffer.

_images/inspector.png

Using the inspector

Here is a list of available keybindings in an inspector buffer:

Keybinding Description
RET Follow a link to inspect the object at point
l Pop to the previous inspected object
g Update the inspector buffer
n or TAB Jump to the next object in the inspector
p or s-TAB Jump to the previous object in the inspector

Troubleshooting

If you run into issues with Indium, this document might help you.

General advice before reporting issues

Issues should be reported on the GitHub issue tracker.

1. If you encounter errors, you can enable debug-on-error in Emacs using M-x toggle-debug-on-error and report an issue with the backtrace.

2. It is also a good idea to turn on Indium’s log mode with M-: (setq indium-client-debug t), and attach to the issue report the contents of the *indium-debug-log* buffer to help resolve the issue.

Attaching the contents of the *indium-process* buffer can help as well in case an error happens in the server process.

The Indium server doesn’t start

First, make sure that indium is installed as documented in the The Indium server section.

If you encounter the error:

"error in process filter: Indium server process error: env: node: No such file or directory"

Chances are that node is not in Emacs’ exec-path. In this case, you can fix it by appending the correct directory to exec-path, or use the exec-path-from-shell package:

(require 'exec-path-from-shell)
(exec-path-from-shell-initialize)

Breakpoints are not set (not using sourcemaps)

If breakpoints do not work, chances are that the project is not configured correctly.

Note

Indium needs to know how to map script source urls to files on disk. It uses the root (alias webRoot) configuration option as the base path, as described in the General configuration page.

Indium provides a command indium-list-script-sources to list all scripts parsed by the backend, displaying their sources mapped to files on disk. Check that the file where you’re trying to add a breakpoint is listed.

Breakpoints and debugging do not work (using sourcemaps)

Correctly mapping sourcemaps to file locations can be tedious (see Using sourcemaps).

Indium provides the command indium-list-sourcemap-sources to help configuring sourcemaps correctly. This command displays a list of all sourcemap sources in the runtime as file paths on disk. Check that your files are listed there.

Indices and tables