Skip to content
Live-code your NodeJS applications
JavaScript Emacs Lisp
Find file
Latest commit ce95d3d May 23, 2013 @mishoo Some fixes
Failed to load latest commit information.
bin init repository Feb 27, 2013
.gitignore init repository Feb 27, 2013
README.md fix link Feb 27, 2013
livenode.el init repository Feb 27, 2013
livenode.js Some fixes May 23, 2013
package.json init repository Feb 27, 2013

README.md

Livenode -- Live-code your NodeJS application

Livenode is a small tool that allows me to evaluate arbitrary statements in a live NodeJS program, without restarting the server. This way I can introduce new functions/variables, or redefine existing ones, and immediately test without losing any context.

See my blog post and screencast.

I've been using it for a week and am quite satisfied with it, but it's essentially a quick hack and bugs are likely.

Install

Just git clone the repository for now and symlink bin/livenode somewhere into your $PATH.

Use with Emacs

This is only tested with Emacs 24.

You need the WebSocket library: https://github.com/ahyatt/emacs-websocket.

Place livenode.el somewhere in your Emacs load path, then add (require 'livenode) to your .emacs. To start your NodeJS server with Livenode, just use livenode path/to/your/app.js. Then you can connect Emacs to the server with M-x livenode and you can use the following:

  • C-M-x -- evaluate the statement at point
  • C-c C-r -- evaluate the region
  • M-x livenode-gencode-region -- do code rewriting on region

Other editors

If your favorite editor is programmable, chances are it will be trivial to add support for it. You need a JSON library and a WebSocket client library. Patches are welcome.

Editor API

Communication between editor and server happens over a WebSocket connection.

Protocol

Messages that travel over this websocket are JSON-encoded arrays containing two or more elements:

REQUEST . . . . . [ ID, "COMMAND", ARG* ]    // editor → server
RESPONSE  . . . . [ ID, "COMMAND", RESULT ]  // server → editor
NOTIFICATION  . . [ 0, "error", ERROR ]      // server → editor

The first element is a request ID. When replying to some particular request, the server will include its ID so you can match the result on the editor side (this is necessary since the protocol is fully asynchronous and there's no classic notion of "response to some request" as in HTTP).

The client (editor) should be prepared to receive anytime notifications (those will have the ID == 0). The only notification supported for now is "error" (this string will be the second element of the array) -- the server will send this in the case of an unhandled exception (those normally bring down the server, but Livenode catches them and forwards to the editor).

When there is an immediate error handling a particular request, the response will contain the string "error" in the second element (rather than the command name) and the error instead of the result. Note that this is different from an unhandled exception.

API

The following commands are supported at this time:

  • "eval" (filename, code) -- evaluate code in the context of the module loaded from filename. filename must be the absolute, fully-resolved (no symlinks) path name of the module.

  • "eval_at_pos" (filename, code, pos) -- evaluate the statement at a given position (pos) in the context of the module identified by filename. Note that code should be the whole code in the editor, for this case, and pos is the cursor position (1-based). I decided to do it this way to lift the burden of parsing and figuring out the statement from the editor—since we already have a proper parser on the server.

  • "rewrite_code" (filename, code) -- apply code rewriting on the given code assuming the context of the module identified by filename.

Both "eval" and "eval_at_pos" return an object that looks like this:

{ code: code, // the rewritten code that has been evaluated
  warn: [ WARNING* ], // an array of warnings
  result: ... }

Additionally, "eval_at_pos" will also include in this object two integers, begin and end, which tell us the position of the statement that has been evaluated (I'm using this in Emacs to flash the statement after evaluation).

The warnings currently reported are only for undeclared variables. A warning looks like this:

{ message: "i.e. Undeclared variable...",
  begin: POSITION,
  end: POSITION }

Again, begin and end are positions that the editor can use to highlight the code that triggered the warning (i.e. the undeclared variable, for now).

Other kinds of warnings might be added in the future.

Something went wrong with that request. Please try again.