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>
    <div id="terminal"
         style="position:relative; width:100%; height:100%"></div>

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 sacrificial DOM node.


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');

You can also call t.installKeyboard() to capture all keyboard input at this point.