Tuesday, August 7, 2012

Run Node.js Express Application from TextMate

First of all

I tried a lot of existing solutions but I could not use one, so I created a new script for it.

Setup

Open Textmate > Preferences > Advanced > Shell Variables and add your node path to the PATH variable (with homebrew append :/usr/local/bin).

Now, let's create a new command. Open Bundles > Bundle Editor > Edit Commands and create a New Bundle (name it whatever you want; I named it JavaScript With Node). Create a new command under your new bundle (name of my command is Run With Node) with the following code:

  #!/usr/bin/env node

  var sys = require("sys"),
      spawn = require('child_process').spawn;

  /*
   * htmlEntities function is from Chris Coyier
   * URL: http://css-tricks.com/snippets/javascript/htmlentities-for-javascript/
   */
  function htmlEntities(str) {
      return String(str).replace(/&/g, '&')
                        .replace(/</g, '&lt;')
                        .replace(/>/g, '&gt;')
                        .replace(/"/g, '&quot;');
  }

  (function(path, file) {
    console.log("<div style='color: green'>Run "
                + path + "/" + file
                + "</div>");
    var app = spawn("node", [path + "/" + file], { cwd: path });
    app.stdout.on('data', function(data) {
      console.log("<div>"
                  + htmlEntities(data)
                  + "</div>");
    });
    app.stderr.on('data', function(data) {
      console.log("<div style='color: red'>"
                  + htmlEntities(data)
                  + "</div>");
    });
    app.on('exit', function(code) {
      console.log('App exited with code ' + code);
    });
  })(process.env.TM_DIRECTORY, 'app.js');
  
  // by Balazs Nadasdi
  // if you find a bug then please send me to yitsushi@gmail.com
  // or find me on Google+

Parameters

Save: Current File
Input: Entire Document
Output: Show as HTML

Optional

Activation: Key Equivalent with ⌘R (Command + R)
Scope Selector: source.js

Additional

If you don't want to create a script for one file (instead of the entire Express application) then use this code (e.g. Run File With Node):

  #!/usr/bin/env node

  var sys = require("sys"),
      spawn = require('child_process').spawn;

  /*
   * htmlEntities function is from Chris Coyier
   * URL: http://css-tricks.com/snippets/javascript/htmlentities-for-javascript/
   */
  function htmlEntities(str) {
      return String(str).replace(/&/g, '&amp;')
                        .replace(/</g, '&lt;')
                        .replace(/>/g, '&gt;')
                        .replace(/"/g, '&quot;');
  }

  (function(path, file) {
    console.log("<div style='color: green'>Run "
                + file
                + "</div>");
    var app = spawn("node", [file], { cwd: path });
    app.stdout.on('data', function(data) {
      console.log("<div>"
                  + htmlEntities(data)
                  + "</div>");
    });
    app.stderr.on('data', function(data) {
      console.log("<div style='color: red'>"
                  + htmlEntities(data)
                  + "</div>");
    });
    app.on('exit', function(code) {
      console.log('App exited with code ' + code);
    });
  })(process.env.TM_DIRECTORY, process.env.TM_FILEPATH);
  
  // by Balazs Nadasdi
  // if you find a bug then please send me to yitsushi@gmail.com
  // or find me on Google+