Compare commits

...
34 Commits
Author SHA1 Message Date
Paris 51fe17ee43 Mark version 0.30 2015-02-25 09:34:12 +02:00
Paris Kasidiaris 1d5737f843 Merge pull request #22 from sourcelair/issue/21
Introduce bufferred attaching to websocket
2015-02-25 09:31:35 +02:00
Paris 13103aecb2 [attach addon] Document with JSDoc 2015-02-24 22:28:47 +02:00
Paris e9d2c806ba [attach addon] Switch indentation to 4 spaces instead of 2 2015-02-24 20:57:28 +02:00
Paris 932ab00a53 Implement buffered attaching
Fixes #21
2015-02-24 20:55:52 +02:00
Paris Kasidiaris 6cfd957697 Merge pull request #20 from akalipetis/issue/19
Pressing Alt + ←/→ does not interfere now with browser
2015-01-28 11:52:55 +02:00
Antonis Kalipetis f00d8964c2 Replaced preventDefault with cancel 2015-01-28 11:20:47 +02:00
Antonis Kalipetis 9ef6b52352 Pressing Alt + ←/→ does not interfere now with browser
Previously, when on Chrome for Windows, if default was not prevented the browser history backward/forward was triggered.

Fixes #19
2015-01-28 11:04:38 +02:00
Paris Kasidiaris 2a9de5e5c0 Merge pull request #17 from sourcelair/issue/8
Bump to v0.29
2015-01-19 19:45:19 +02:00
paris 761e5db937 Merged with master 2015-01-19 19:45:03 +02:00
paris 391d8f4097 Bump version to 0.29 and copyright year to 2015 2015-01-19 19:07:28 +02:00
paris af39a3fcc0 Fix #8
Also fix some Internet Explorer incompatibilities
2015-01-19 19:06:17 +02:00
Paris Kasidiaris 69153c04a6 Merge pull request #16 from sourcelair/addon/linkify
Implement conversion of URLs to link elements in a terminal view
2015-01-15 12:14:23 +02:00
paris 85abfb8151 Bump version to 0.28 2015-01-06 13:12:31 +02:00
paris e100ee0cc0 [addon linkify] Further optimize URL algorithm 2015-01-06 13:03:07 +02:00
Paris Kasidiaris d5d48cd48a Merge pull request #15 from sourcelair/issue/14
Jump words back and forward with "Alt + ←" and "Alt + →"
2015-01-06 12:37:45 +02:00
paris 3e7ab290fa [addon linkify] Remove console.log 2015-01-05 16:07:29 +02:00
paris 43ac453db1 [addon linkify] Improve start and end clauses 2015-01-05 16:05:14 +02:00
paris d0d87505a9 [addon linkify] Improve URL to link conversion algorithm 2015-01-04 22:27:14 +02:00
paris c8a497eb82 [addon linkify] Fine-grained module and documented almost everything 2015-01-04 20:39:57 +02:00
paris 523ff9908f [addon linkify] Set up proper initialization of add-on
- Also created a demo page for the addon
2015-01-04 15:45:26 +02:00
paris 72ed03adcb Fix #14 2015-01-04 15:33:21 +02:00
paris b60903a2ae [addon linkify] Start working on "linkifying" URLs in the terminal 2015-01-04 15:08:36 +02:00
paris c5af270885 Mark version 0.27 2014-11-24 17:42:17 +02:00
Antonis Kalipetis 510990c312 Merge pull request #11 from sourcelair/issue/9
Fixed incorrect row/column calculation in Firefox
2014-11-24 17:36:18 +02:00
akalipetis 37be8e0f34 Fixed correct fitting of Terminal 2014-11-24 17:24:21 +02:00
paris 8dd80566d0 Fix #9
- Calculate character width by using the cursor instead of custom hack in fit addon
- Increment character width by 1 in Firefox, since it seems to have a bug in calculating width of specific elements
2014-11-17 17:08:14 +02:00
paris c6a7e15b03 [fit addon] Restore row content after proposing geometry
- Restore `subjectRow.innerHTML`, using the `contentBuffer`
- Bump version to 0.25
2014-11-17 12:36:13 +02:00
paris 87979aeed4 Bind window to AMD module
- Bind window to Xterm AMD module
- Fix typo in fit addon
- Bump version to 0.24
2014-11-17 12:28:52 +02:00
paris 615f633f25 [fit addon] Introduce proposeGeometry method
- Introduce new method to propose optimal geometry for the current terminal
- Bump version to 0.23
2014-11-17 12:21:05 +02:00
paris 567b39dc98 Fix #6 2014-09-22 05:48:05 +00:00
paris 0b2bdb182b Bump version to 0.22 2014-09-18 11:11:45 +00:00
paris 4ce1440fb8 [addon attach] Make reference to socket fail-safe 2014-09-18 11:11:29 +00:00
paris f24c020aca [addon attach] Fix reference error
Also bump version to 0.21
2014-09-18 10:15:10 +00:00
10 changed files with 350 additions and 77 deletions
+1 -1
View File
@@ -14,6 +14,6 @@ If you contribute code to this project, you are implicitly allowing your code to
## License
Copyright (c) 2014, SourceLair, Ltd (www.sourcelair.com) (MIT License)
Copyright (c) 2014-2015, SourceLair, Ltd (www.sourcelair.com) (MIT License)
Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+66 -25
View File
@@ -1,7 +1,7 @@
/*
* Implements the attach method, that
* attaches the terminal to a WebSocket stream.
*
*
* The bidirectional argument indicates, whether the terminal should
* send data to the socket as well and is true, by default.
*/
@@ -15,40 +15,81 @@
} else {
/*
* Plain browser environment
*/
*/
attach(this.Xterm);
}
})(function (Xterm) {
Xterm.prototype.attach = function (socket, bidirectional) {
var term = this;
/**
* 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) {
var term = this;
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
this.socket = socket;
bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional;
this.socket = socket;
term._getMessage = function (ev) {
term.write(ev.data);
};
term._sendData = function (data) {
socket.send(data);
};
term._flushBuffer = function () {
term.write(term._attachSocketBuffer);
term._attachSocketBuffer = null;
clearTimeout(term._attachSocketBufferTimer);
term._attachSocketBufferTimer = null;
};
socket.addEventListener('message', _getMessage);
term._pushToBuffer = function (data) {
if (term._attachSocketBuffer) {
term._attachSocketBuffer += data;
} else {
term._attachSocketBuffer = data;
setTimeout(term._flushBuffer, 10);
}
};
if (bidirectional) {
this.on('data', _sendData);
}
socket.addEventListener('close', term.detach.bind(term, socket));
socket.addEventListener('error', term.detach.bind(term, socket));
term._getMessage = function (ev) {
if (buffered) {
term._pushToBuffer(ev.data);
} else {
term.write(ev.data);
}
};
term._sendData = function (data) {
socket.send(data);
};
socket.addEventListener('message', term._getMessage);
if (bidirectional) {
this.on('data', term._sendData);
}
socket.addEventListener('close', term.detach.bind(term, socket));
socket.addEventListener('error', term.detach.bind(term, socket));
};
/**
* 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) {
var term = this;
var term = this;
term.off('data', term._sendData);
socket.removeEventListener('message', term._getMessage);
term.off('data', term._sendData);
delete term.socket;
socket = (typeof socket == 'undefined') ? term.socket : socket;
if (socket) {
socket.removeEventListener('message', term._getMessage);
}
delete term.socket;
};
});
+44 -29
View File
@@ -24,36 +24,51 @@
fit(this.Xterm);
}
})(function (Xterm) {
Xterm.prototype.proposeGeometry = function () {
var parentElementStyle = window.getComputedStyle(this.element.parentElement),
parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')),
elementStyle = window.getComputedStyle(this.element),
elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')),
elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')),
availableHeight = parentElementHeight - elementPaddingVer,
availableWidth = parentElementWidth - elementPaddingHor,
container = this.rowContainer,
subjectRow = this.rowContainer.firstElementChild,
contentBuffer = subjectRow.innerHTML,
characterHeight,
rows,
characterWidth,
cols,
geometry;
subjectRow.style.display = 'inline';
subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace
characterWidth = parseInt(subjectRow.offsetWidth);
subjectRow.style.display = ''; // Revert style before calculating height, since they differ.
characterHeight = parseInt(subjectRow.offsetHeight);
subjectRow.innerHTML = contentBuffer;
rows = parseInt(availableHeight / characterHeight);
/*
* The following hack takes place in order to get "fit" work properly
* in Mozilla Firefox.
* Most probably, because of a dimension calculation bug, Firefox
* calculates the width to be 1px less than it is actually drawn on
* screen.
*/
if (navigator.userAgent.match(/Firefox/)) {
characterWidth++;
}
cols = parseInt(availableWidth / characterWidth);
geometry = {cols: cols, rows: rows};
return geometry;
};
Xterm.prototype.fit = function () {
var container = this.rowContainer,
subjectRow = this.rowContainer.firstElementChild,
rows,
contentBuffer,
characterWidth,
cols;
var geometry = this.proposeGeometry();
subjectRow.style.display = 'inline';
contentBuffer = subjectRow.textContent;
subjectRow.innerHTML = ' '; /* Arbitrary character to calculate its dimensions */
characterWidth = parseInt(subjectRow.offsetWidth);
characterHeight = parseInt(subjectRow.offsetHeight);
subjectRow.style.display = '';
cols = container.offsetWidth / characterWidth;
cols = parseInt(cols);
var parentElementStyle = window.getComputedStyle(this.element.parentElement),
parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
elementStyle = window.getComputedStyle(this.element),
elementPadding = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')),
availableHeight = parentElementHeight - elementPadding,
rowHeight = this.rowContainer.firstElementChild.offsetHeight;
rows = parseInt(availableHeight / rowHeight);
this.resize(cols, rows);
this.resize(geometry.cols, geometry.rows);
};
});
+36
View File
@@ -0,0 +1,36 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="../../src/xterm.css" />
<link rel="stylesheet" href="../../demo/style.css" />
<script src="../../src/xterm.js"></script>
<script src="linkify.js"></script>
<style>
body {
color: #111;
}
#terminal-container {
max-width: 900px;
margin: 0 auto;
}
#terminal-container a {
color: #fff;
}
</style>
</head>
<body>
<div id="terminal-container"></div>
<script>
var term = new Terminal(),
container = document.getElementById('terminal-container');
term.open(container);
term.writeln('Hello, welcome to xterm.js');
term.writeln('');
term.writeln('Check it out at github.com/sourcelair/xterm.js');
term.linkify();
</script>
</body>
</html>
+165
View File
@@ -0,0 +1,165 @@
(function (linkify) {
if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../src/xterm'], linkify);
} else {
/*
* Plain browser environment
*/
linkify(this.Xterm);
}
})(function (Xterm) {
'use strict';
/**
* This module provides methods for convertings valid URL substrings
* into HTML anchor elements (links), inside a terminal view.
*
* @module xterm/addons/linkify/linkify
*/
var exports = {},
protocolClause = '(https?:\\/\\/)',
domainCharacterSet = '[\\da-z\\.-]+',
negatedDomainCharacterSet = '[^\\da-z\\.-]+',
domainBodyClause = '(' + domainCharacterSet + ')',
tldClause = '([a-z\\.]{2,6})',
hostClause = domainBodyClause + '\\.' + tldClause,
pathClause = '([\\/\\w\\.-]*)*\\/?',
negatedPathCharacterSet = '[^\\/\\w\\.-]+',
bodyClause = hostClause + pathClause,
start = '(?:^|' + negatedDomainCharacterSet + ')(',
end = ')($|' + negatedPathCharacterSet + ')',
urlClause = start + protocolClause + '?' + bodyClause + end,
urlRegex = new RegExp(urlClause);
/**
* Converts all valid URLs found in the given terminal line into
* hyperlinks. The terminal line can be either the HTML element itself
* or the index of the termina line in the children of the terminal
* rows container.
*
* @param {Xterm} terminal - The terminal that owns the given line.
* @param {number|HTMLDivElement} line - The terminal line that should get
* "linkified".
* @emits linkify
* @emits linkify:line
*/
exports.linkifyTerminalLine = function (terminal, line) {
if (typeof line == 'number') {
line = terminal.rowContainer.children[line];
} else if (! (line instanceof HTMLDivElement)) {
var message = 'The "line" argument should be either a number';
message += ' or an HTMLDivElement';
throw new TypeError(message);
}
var buffer = document.createElement('span'),
nodes = line.childNodes;
for (var j=0; j<nodes.length; j++) {
var node = nodes[j];
/*
* Since we cannot access the TextNode's HTML representation
* from the instance itself, we assign its data as textContent
* to a dummy buffer span, in order to retrieve the TextNode's
* HTML representation from the buffer's innerHTML.
*/
buffer.textContent = node.data;
var nodeHTML = buffer.innerHTML;
/*
* Apply function only on TextNodes
*/
if (node.nodeType != node.TEXT_NODE) {
continue;
}
var match = node.data.match(urlRegex);
/*
* If no URL was found in the current text, return.
*/
if (!match) {
continue;
}
var url = match[1],
startsWithProtocol = new RegExp('^' + protocolClause),
urlHasProtocol = url.match(startsWithProtocol),
href = (urlHasProtocol) ? url : 'http://' + url,
link = '<a href="' + href + '" >' + url + '</a>',
newHTML = nodeHTML.replace(url, link);
line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML);
}
/**
* This event gets emitted when conversion of all URL susbtrings
* to HTML anchor elements (links) has finished, for a specific
* line of the current Xterm instance.
*
* @event linkify:line
*/
terminal.emit('linkify:line', line);
};
/**
* Converts all valid URLs found in the terminal view into hyperlinks.
*
* @param {Xterm} terminal - The terminal that should get "linkified".
* @emits linkify
* @emits linkify:line
*/
exports.linkify = function (terminal) {
var rows = terminal.rowContainer.children;
for (var i=0; i<rows.length; i++) {
var line = rows[i];
exports.linkifyTerminalLine(terminal, line);
}
/**
* This event gets emitted when conversion of all URL substrings to
* HTML anchor elements (links) has finished for the current Xterm
* instance's view.
*
* @event linkify
*/
terminal.emit('linkify');
};
/*
* Extend Xterm prototype.
*/
/**
* Converts all valid URLs found in the current terminal linte into
* hyperlinks.
*
* @memberof Xterm
* @param {number|HTMLDivElement} line - The terminal line that should get
* "linkified".
*/
Xterm.prototype.linkifyTerminalLine = function (line) {
return exports.linkifyTerminalLine(this, line);
};
/**
* Converts all valid URLs found in the current terminal into hyperlinks.
*
* @memberof Xterm
*/
Xterm.prototype.linkify = function () {
return exports.linkify(this);
};
return exports;
});
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "xterm.js",
"version": "0.20",
"version": "0.30",
"ignore": ["demo", "docs", "test", ".gitignore"]
}
+11 -5
View File
@@ -1,12 +1,13 @@
var terminalContainer = document.getElementById('terminal-container'),
term = new Terminal();
term = new Terminal(),
prompt = '> ';
term.open(terminalContainer);
term.fit();
term.prompt = function () {
term.write('\r\n> ');
}
term.write('\r\n' + prompt);
};
term.writeln('Welcome to xterm.js');
term.writeln('Just type some keys in the prompt below.');
@@ -16,10 +17,15 @@ term.prompt();
term.on('key', function (key, ev) {
var printable = (!ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey);
if (ev.keyIdentifier == 'Enter') {
if (ev.keyCode == 13) {
term.prompt();
} else if (ev.keyCode == 8) {
term.write('\b \b');
/*
* Do not delete the prompt
*/
if (term.x > 2) {
term.write('\b \b');
}
} else if (printable) {
term.write(key);
}
+3 -3
View File
@@ -44,16 +44,16 @@ master_doc = 'index'
# General information about the project.
project = u'xterm.js'
copyright = u'2014, SourceLair Limited'
copyright = u'2015, SourceLair Limited'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.20'
version = '0.30'
# The full version, including alpha/beta/rc tags.
release = '0.20 Alpha'
release = '0.30 Alpha'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+12 -9
View File
@@ -32,28 +32,31 @@
*/
/*
* Default style for xterm.js
*/
* Default style for xterm.js
*/
.xterm {
.terminal {
background-color: #000;
color: #fff;
outline: none;
font-family: courier-new, courier, monospace;
position: relative;
}
.xterm .terminal-cursor {
.terminal:focus {
outline: none;
}
.terminal .terminal-cursor {
background-color: #fff;
color: #000;
}
.xterm .xterm-helpers {
.terminal .xterm-helpers {
position: absolute;
top: 0;
}
.xterm .xterm-helper-textarea {
.terminal .xterm-helper-textarea {
opacity: 0;
width: 0;
height: 0;
@@ -61,8 +64,8 @@
}
/*
* Determine default colors for xterm.js
*/
* Determine default colors for xterm.js
*/
.terminal .xterm-bold {
font-weight: bold;
}
+11 -4
View File
@@ -36,7 +36,7 @@
/*
* Require.js is available
*/
define([], xterm);
define([], xterm.bind(window));
} else {
/*
* Plain browser environment
@@ -2200,16 +2200,23 @@
break;
// left-arrow
case 37:
if (this.applicationCursor) {
if (ev.altKey) {
this.cancel(ev, true);
key = '\x1bb' // Jump a word back
break;
} else if (this.applicationCursor) {
key = '\x1bOD'; // SS3 as ^[O for 7-bit
//key = '\x8fD'; // SS3 as 0x8f for 8-bit
break;
}
key = '\x1b[D';
break;
// right-arrow
case 39:
if (this.applicationCursor) {
if (ev.altKey) {
this.cancel(ev, true);
key = '\x1bf' // Jump a word forward
break;
} else if (this.applicationCursor) {
key = '\x1bOC';
break;
}