Embedding hterm

This is a quick overview describing how to use hterm in your own application. Please direct any questions to the chromium-hterm mailing list.

Step 1, Get the code

The “libapps” git repository contains hterm and its dependency. Clone this repo into a parent directory of your choice. In this example we'll create ~/src/libapps/:

$ mkdir ~/src
$ cd ~/src
$ git clone https://chromium.googlesource.com/apps/libapps

Step 2, Build hterm

The build process for hterm bundles some resources as JavaScript source and concatenates the JavaScript into a single file. It only works on Linux and BSD based systems (yes, OS X should work). To build hterm, run...

$ cd ~/src/libapps
$ LIBDOT_SEARCH_PATH=$(pwd) ./libdot/bin/concat.sh -i \
   ./hterm/concat/hterm_all.concat -o /path/to/hterm_all.js

Replace /path/to/hterm_all.js with a path to where you'd like the resulting JavaScript file to live.

Step 3, Include hterm in your app

Include the generated hterm_all.js file in your app in an appropriate manner. This step should be self evident.

Step 4, Initialize hterm

You'll want a sacrificial DOM node which will become the terminal widget. It should be a div which is either position: relative or position: absolute.

In our example, we'll assume this DOM:

<!DOCTYPE html>
<html>
  <body>
    <div id="terminal"
         style="position:relative; width:100%; height:100%"></div>
  </body>
</html>

You'll also need to choose a storage implementation. This is the backing store that hterm will use to read and write preferences. This should be one of:

// If you are a cross-browser web app and want to use window.localStorage
hterm.defaultStorage = new lib.storage.Local()

// If you are a cross-browser web app and want in-memory storage only
hterm.defaultStorage = new lib.storage.Memory()

// If you are a Chrome app and want sync storage
hterm.defaultStorage = new lib.storage.Chrome(chrome.storage.sync)

// If you are a Chrome app and want local storage
hterm.defaultStorage = new lib.storage.Chrome(chrome.storage.local)

Now create an instance of hterm.Terminal:

// opt_profileName is the name of the terminal profile to load, or "default" if
// not specified.  If you're using one of the persistent storage
// implementations then this will scope all preferences read/writes to this
// name.
var t = new hterm.Terminal(opt_profileName)

Now write an onTerminalReady handler. This will fire once, when the terminal is initialized and ready for use.

t.onTerminalReady = function() {

  // Create a new terminal IO object and give it the foreground.
  // (The default IO object just prints warning messages about unhandled
  // things to the the JS console.)
  var io = t.io.push();

  io.onVTKeystroke = function(str) {
    // Do something useful with str here.
    // For example, Secure Shell forwards the string onto the NaCl plugin.
  };

  io.sendString = function(str) {
    // Just like a keystroke, except str was generated by the
    // terminal itself.
    // Most likely you'll do the same this as onVTKeystroke.
  };

  io.onTerminalResize = function(columns, rows) {
    // React to size changes here.
    // Secure Shell pokes at NaCl, which eventually results in
    // some ioctls on the host.
  };

  // You can call io.push() to foreground a fresh io context, which can
  // be uses to give control of the terminal to something else.  When that
  // thing is complete, should call io.pop() to restore control to the
  // previous io object.
};

Once you've registered your onTerminalReady handler you can connect the terminal to sacrifical DOM node.

t.decorate(document.quertSelector('#terminal'));

Step 5, Write to the terminal.

Once onTerminalReady fires, you're free to start outputting text to the terminal!

t.io.print('Print a string without a newline');
t.io.println('Print a string and add CRLF');