--- /dev/null
+{
+ "name": "xterm.terminado",
+ "main": "terminado.js",
+ "private": true
+}
--- /dev/null
+/*
+ * Implements the attach method that
+ * attaches the terminal to a Terminado WebSocket stream.
+ *
+ * The bidirectional argument indicates, whether the terminal should
+ * send data to the socket as well and is true, by default.
+ */
+
+(function (attach) {
+ if (typeof exports === 'object' && typeof module === 'object') {
+ /*
+ * CommonJS environment
+ */
+ module.exports = attach(require('../../src/xterm'));
+ } else if (typeof define == 'function') {
+ /*
+ * Require.js is available
+ */
+ define(['../../src/xterm'], attach);
+ } else {
+ /*
+ * Plain browser environment
+ */
+ attach(window.Terminal);
+ }
+})(function (Xterm) {
+ 'use strict';
+
+ /**
+ * This module provides methods for attaching a terminal to a WebSocket
+ * stream.
+ *
+ * @module xterm/addons/attach/attach
+ */
+ var exports = {};
+
+ /**
+ * Attaches the given terminal to the given socket.
+ *
+ * @param {Xterm} term - The terminal to be attached to the given socket.
+ * @param {WebSocket} socket - The socket to attach the current terminal.
+ * @param {boolean} bidirectional - Whether the terminal should send data
+ * to the socket as well.
+ * @param {boolean} buffered - Whether the rendering of incoming data
+ * should happen instantly or at a maximum
+ * frequency of 1 rendering per 10ms.
+ */
+ exports.attach = function (term, socket, bidirectional, buffered) {
+ bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
+ term.socket = socket;
+
+ term._flushBuffer = function () {
+ term.write(term._attachSocketBuffer);
+ term._attachSocketBuffer = null;
+ clearTimeout(term._attachSocketBufferTimer);
+ term._attachSocketBufferTimer = null;
+ };
+
+ term._pushToBuffer = function (data) {
+ if (term._attachSocketBuffer) {
+ term._attachSocketBuffer += data;
+ } else {
+ term._attachSocketBuffer = data;
+ setTimeout(term._flushBuffer, 10);
+ }
+ };
+
+ term._getMessage = function (ev) {
+ var data = JSON.parse(ev.data)
+ if( data[0] == "stdout" ) {
+ if (buffered) {
+ term._pushToBuffer(data[1]);
+ } else {
+ term.write(data[1]);
+ }
+ }
+ };
+
+ term._sendData = function (data) {
+ socket.send(JSON.stringify(['stdin', data]));
+ };
+
+ term._setSize = function (size) {
+ socket.send(JSON.stringify(['set_size', size.rows, size.cols]));
+ };
+
+ socket.addEventListener('message', term._getMessage);
+
+ if (bidirectional) {
+ term.on('data', term._sendData);
+ }
+ term.on('resize', term._setSize);
+
+ socket.addEventListener('close', term.detach.bind(term, socket));
+ socket.addEventListener('error', term.detach.bind(term, socket));
+ };
+
+ /**
+ * Detaches the given terminal from the given socket
+ *
+ * @param {Xterm} term - The terminal to be detached from the given socket.
+ * @param {WebSocket} socket - The socket from which to detach the current
+ * terminal.
+ */
+ exports.detach = function (term, socket) {
+ term.off('data', term._sendData);
+
+ socket = (typeof socket == 'undefined') ? term.socket : socket;
+
+ if (socket) {
+ socket.removeEventListener('message', term._getMessage);
+ }
+
+ delete term.socket;
+ };
+
+ /**
+ * Attaches the current terminal to the given socket
+ *
+ * @param {WebSocket} socket - The socket to attach the current terminal.
+ * @param {boolean} bidirectional - Whether the terminal should send data
+ * to the socket as well.
+ * @param {boolean} buffered - Whether the rendering of incoming data
+ * should happen instantly or at a maximum
+ * frequency of 1 rendering per 10ms.
+ */
+ Xterm.prototype.attach = function (socket, bidirectional, buffered) {
+ return exports.attach(this, socket, bidirectional, buffered);
+ };
+
+ /**
+ * Detaches the current terminal from the given socket.
+ *
+ * @param {WebSocket} socket - The socket from which to detach the current
+ * terminal.
+ */
+ Xterm.prototype.detach = function (socket) {
+ return exports.detach(this, socket);
+ };
+
+ return exports;
+});
+++ /dev/null
-Using Terminado with Xterm.js
-=============================
-
-Xterm.js is a very flexible system, and as such can be mapped to work with a wide variety of websocket/terminal backends. [Terminado](https://github.com/takluyver/terminado) is one such backend written in Python using `Tornado` as the underlying web framework. This directory shows a more-or-less barebones example of integrating `Terminado` and `Xterm.js`. To do so requires some small edits to `Xterm.js`'s `attach.js` to change the websocket communication format. Briefly, `Terminado` wraps messages in arrays with an element denoting what kind of data it holds, and so rather than simply sending user-typed data directly, one sends `['stdin', data]`.
-
-To run this example, first install Terminado via `pip install terminado`, then simply run `python ./app.py` and connect to http://localhost:8000 to open a shell on localhost.
+++ /dev/null
-"""A single common terminal for all websockets.
-"""
-import tornado.web
-from tornado.ioloop import IOLoop
-from terminado import TermSocket, SingleTermManager
-
-if __name__ == '__main__':
- term_manager = SingleTermManager(shell_command=['bash'])
- handlers = [
- (r"/websocket", TermSocket, {'term_manager': term_manager}),
- (r"/()", tornado.web.StaticFileHandler, {'path':'index.html'}),
- (r"/terminado_attach.js()", tornado.web.StaticFileHandler, {'path':'terminado_attach.js'}),
- ]
- app = tornado.web.Application(handlers, static_path="../dist/")
- app.listen(8010)
- IOLoop.current().start()
+++ /dev/null
-<!DOCTYPE html>
-<head>
-<meta charset="UTF-8">
-<title>Terminado Xterm.js example page</title>
-<style>
- html {
- background: #555;
- height: 100vh;
- }
-
- body {
- min-height: 100vh;
- }
-
- #terminal-container {
- position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- width: auto;
- height: auto;
- z-index: 255;
- }
-</style>
-<link rel="stylesheet" href="/static/xterm.css"/>
-<script src="/static/xterm.js"></script>
-<script src="/terminado_attach.js"></script>
-<script>
-var term,
- charWidth,
- charHeight;
-
-// This chunk of code gratefully stolen/adapted from fit.js
-function calculate_character_dimensions() {
- subjectRow = term.rowContainer.firstElementChild;
- contentBuffer = subjectRow.innerHTML;
-
- subjectRow.style.display = 'inline';
- subjectRow.innerHTML = 'W';
- charWidth = subjectRow.getBoundingClientRect().width;
- subjectRow.style.display = '';
- charHeight = parseInt(subjectRow.offsetHeight);
- subjectRow.innerHTML = contentBuffer;
-}
-
-function createTerminal(websocket_url) {
- var terminalContainer = document.getElementById('terminal-container');
-
- // Clean terminal
- while (terminalContainer.children.length) {
- terminalContainer.removeChild(terminalContainer.children[0]);
- }
-
- term = new Terminal({
- cursorBlink: true
- });
-
- protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
- socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + websocket_url;
-
- term.open(terminalContainer);
- var socket = new WebSocket(socketURL);
- socket.onopen = function() {
- term.attach(socket);
- term._initialized = true;
-
- terminalContainer.style.width = '100vw';
- terminalContainer.style.height = '100vh';
- calculate_character_dimensions();
- window.onresize = function() {
- cols = Math.floor(terminalContainer.getBoundingClientRect().width/charWidth);
- rows = Math.floor(terminalContainer.getBoundingClientRect().height/charHeight);
- term.resize(cols, rows);
- }
- window.onresize()
- }
-}
-
-window.onload = function() {
- // Connect to Terminado, listening on /websocket
- createTerminal('/websocket')
-}
-</script>
-</head>
-<body>
-<div id="terminal-container"></div>
-</pre>
-</body>
+++ /dev/null
-/*
- * Implements the attach method that
- * attaches the terminal to a Terminado WebSocket stream.
- *
- * The bidirectional argument indicates, whether the terminal should
- * send data to the socket as well and is true, by default.
- */
-
-(function (attach) {
- if (typeof exports === 'object' && typeof module === 'object') {
- /*
- * CommonJS environment
- */
- module.exports = attach(require('../../src/xterm'));
- } else if (typeof define == 'function') {
- /*
- * Require.js is available
- */
- define(['../../src/xterm'], attach);
- } else {
- /*
- * Plain browser environment
- */
- attach(window.Terminal);
- }
-})(function (Xterm) {
- 'use strict';
-
- /**
- * This module provides methods for attaching a terminal to a WebSocket
- * stream.
- *
- * @module xterm/addons/attach/attach
- */
- var exports = {};
-
- /**
- * Attaches the given terminal to the given socket.
- *
- * @param {Xterm} term - The terminal to be attached to the given socket.
- * @param {WebSocket} socket - The socket to attach the current terminal.
- * @param {boolean} bidirectional - Whether the terminal should send data
- * to the socket as well.
- * @param {boolean} buffered - Whether the rendering of incoming data
- * should happen instantly or at a maximum
- * frequency of 1 rendering per 10ms.
- */
- exports.attach = function (term, socket, bidirectional, buffered) {
- bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
- term.socket = socket;
-
- term._flushBuffer = function () {
- term.write(term._attachSocketBuffer);
- term._attachSocketBuffer = null;
- clearTimeout(term._attachSocketBufferTimer);
- term._attachSocketBufferTimer = null;
- };
-
- term._pushToBuffer = function (data) {
- if (term._attachSocketBuffer) {
- term._attachSocketBuffer += data;
- } else {
- term._attachSocketBuffer = data;
- setTimeout(term._flushBuffer, 10);
- }
- };
-
- term._getMessage = function (ev) {
- var data = JSON.parse(ev.data)
- if( data[0] == "stdout" ) {
- if (buffered) {
- term._pushToBuffer(data[1]);
- } else {
- term.write(data[1]);
- }
- }
- };
-
- term._sendData = function (data) {
- socket.send(JSON.stringify(['stdin', data]));
- };
-
- term._setSize = function (size) {
- socket.send(JSON.stringify(['set_size', size.rows, size.cols]));
- };
-
- socket.addEventListener('message', term._getMessage);
-
- if (bidirectional) {
- term.on('data', term._sendData);
- }
- term.on('resize', term._setSize);
-
- socket.addEventListener('close', term.detach.bind(term, socket));
- socket.addEventListener('error', term.detach.bind(term, socket));
- };
-
- /**
- * Detaches the given terminal from the given socket
- *
- * @param {Xterm} term - The terminal to be detached from the given socket.
- * @param {WebSocket} socket - The socket from which to detach the current
- * terminal.
- */
- exports.detach = function (term, socket) {
- term.off('data', term._sendData);
-
- socket = (typeof socket == 'undefined') ? term.socket : socket;
-
- if (socket) {
- socket.removeEventListener('message', term._getMessage);
- }
-
- delete term.socket;
- };
-
- /**
- * Attaches the current terminal to the given socket
- *
- * @param {WebSocket} socket - The socket to attach the current terminal.
- * @param {boolean} bidirectional - Whether the terminal should send data
- * to the socket as well.
- * @param {boolean} buffered - Whether the rendering of incoming data
- * should happen instantly or at a maximum
- * frequency of 1 rendering per 10ms.
- */
- Xterm.prototype.attach = function (socket, bidirectional, buffered) {
- return exports.attach(this, socket, bidirectional, buffered);
- };
-
- /**
- * Detaches the current terminal from the given socket.
- *
- * @param {WebSocket} socket - The socket from which to detach the current
- * terminal.
- */
- Xterm.prototype.detach = function (socket) {
- return exports.detach(this, socket);
- };
-
- return exports;
-});