Merge remote-tracking branch 'ups/master' into 553_find_api

This commit is contained in:
Daniel Imms
2017-07-08 23:07:57 -07:00
20 changed files with 12813 additions and 203 deletions
+5
View File
@@ -56,8 +56,13 @@ export class InputHandler implements IInputHandler {
this._terminal.x = 0;
this._terminal.y++;
if (this._terminal.y > this._terminal.scrollBottom) {
// Insert a new line, scroll and mark as a wrapped line
this._terminal.y--;
this._terminal.scroll(true);
} else {
// The line already exists (eg. the initial viewport), mark it as a
// wrapped line
this._terminal.lines.get(this._terminal.y).isWrapped = true;
}
} else {
if (ch_width === 2) // FIXME: check for xterm behavior
+6 -7
View File
@@ -17,6 +17,7 @@ class TestLinkifier extends Linkifier {
}
describe('Linkifier', () => {
let dom: jsdom.JSDOM;
let window: Window;
let document: Document;
@@ -24,13 +25,11 @@ describe('Linkifier', () => {
let rows: HTMLElement[];
let linkifier: TestLinkifier;
beforeEach(done => {
jsdom.env('', (err, w) => {
window = w;
document = window.document;
linkifier = new TestLinkifier();
done();
});
beforeEach(() => {
dom = new jsdom.JSDOM('');
window = dom.window;
document = window.document;
linkifier = new TestLinkifier();
});
function addRow(html: string) {
+2 -1
View File
@@ -200,7 +200,8 @@ export class Renderer {
}
currentElement = this._spanElementObjectPool.acquire();
if (data === -1) {
currentElement.classList.add('reverse-video', 'terminal-cursor');
currentElement.classList.add('reverse-video');
currentElement.classList.add('terminal-cursor');
} else {
let bg = data & 0x1ff;
let fg = (data >> 9) & 0x1ff;
+24 -33
View File
@@ -31,6 +31,7 @@ class TestSelectionManager extends SelectionManager {
}
describe('SelectionManager', () => {
let dom: jsdom.JSDOM;
let window: Window;
let document: Document;
@@ -39,15 +40,13 @@ describe('SelectionManager', () => {
let rowContainer: HTMLElement;
let selectionManager: TestSelectionManager;
beforeEach(done => {
jsdom.env('', (err, w) => {
window = w;
document = window.document;
buffer = new CircularList<any>(100);
terminal = <any>{ cols: 80, rows: 2 };
selectionManager = new TestSelectionManager(terminal, buffer, rowContainer, null);
done();
});
beforeEach(() => {
dom = new jsdom.JSDOM('');
window = dom.window;
document = window.document;
buffer = new CircularList<any>(100);
terminal = <any>{ cols: 80, rows: 2 };
selectionManager = new TestSelectionManager(terminal, buffer, rowContainer, null);
});
function stringToRow(text: string): [number, string, number][] {
@@ -143,46 +142,38 @@ describe('SelectionManager', () => {
assert.equal(selectionManager.selectionText, 'foo');
});
it('should select up to non-path characters that are commonly adjacent to paths', () => {
buffer.push(stringToRow(':ab:(cd)[ef]{gh}\'ij"'));
buffer.push(stringToRow('(cd)[ef]{gh}\'ij"'));
selectionManager.selectWordAt([0, 0]);
assert.equal(selectionManager.selectionText, ':ab');
selectionManager.selectWordAt([1, 0]);
assert.equal(selectionManager.selectionText, 'ab');
selectionManager.selectWordAt([2, 0]);
assert.equal(selectionManager.selectionText, 'ab');
selectionManager.selectWordAt([3, 0]);
assert.equal(selectionManager.selectionText, 'ab:');
selectionManager.selectWordAt([4, 0]);
assert.equal(selectionManager.selectionText, '(cd');
selectionManager.selectWordAt([5, 0]);
selectionManager.selectWordAt([1, 0]);
assert.equal(selectionManager.selectionText, 'cd');
selectionManager.selectWordAt([6, 0]);
selectionManager.selectWordAt([2, 0]);
assert.equal(selectionManager.selectionText, 'cd');
selectionManager.selectWordAt([7, 0]);
selectionManager.selectWordAt([3, 0]);
assert.equal(selectionManager.selectionText, 'cd)');
selectionManager.selectWordAt([8, 0]);
selectionManager.selectWordAt([4, 0]);
assert.equal(selectionManager.selectionText, '[ef');
selectionManager.selectWordAt([9, 0]);
selectionManager.selectWordAt([5, 0]);
assert.equal(selectionManager.selectionText, 'ef');
selectionManager.selectWordAt([10, 0]);
selectionManager.selectWordAt([6, 0]);
assert.equal(selectionManager.selectionText, 'ef');
selectionManager.selectWordAt([11, 0]);
selectionManager.selectWordAt([7, 0]);
assert.equal(selectionManager.selectionText, 'ef]');
selectionManager.selectWordAt([12, 0]);
selectionManager.selectWordAt([8, 0]);
assert.equal(selectionManager.selectionText, '{gh');
selectionManager.selectWordAt([13, 0]);
selectionManager.selectWordAt([9, 0]);
assert.equal(selectionManager.selectionText, 'gh');
selectionManager.selectWordAt([14, 0]);
selectionManager.selectWordAt([10, 0]);
assert.equal(selectionManager.selectionText, 'gh');
selectionManager.selectWordAt([15, 0]);
selectionManager.selectWordAt([11, 0]);
assert.equal(selectionManager.selectionText, 'gh}');
selectionManager.selectWordAt([16, 0]);
selectionManager.selectWordAt([12, 0]);
assert.equal(selectionManager.selectionText, '\'ij');
selectionManager.selectWordAt([17, 0]);
selectionManager.selectWordAt([13, 0]);
assert.equal(selectionManager.selectionText, 'ij');
selectionManager.selectWordAt([18, 0]);
selectionManager.selectWordAt([14, 0]);
assert.equal(selectionManager.selectionText, 'ij');
selectionManager.selectWordAt([19, 0]);
selectionManager.selectWordAt([15, 0]);
assert.equal(selectionManager.selectionText, 'ij"');
});
});
+3 -2
View File
@@ -43,7 +43,7 @@ const CLEAR_MOUSE_DISTANCE = 10;
* A string containing all characters that are considered word separated by the
* double click to select work logic.
*/
const WORD_SEPARATORS = ' ()[]{}:\'"';
const WORD_SEPARATORS = ' ()[]{}\'"';
// TODO: Move these constants elsewhere, they belong in a buffer or buffer
// data/line class.
@@ -179,6 +179,7 @@ export class SelectionManager extends EventEmitter {
*/
public setBuffer(buffer: CircularList<any>): void {
this._buffer = buffer;
this.clearSelection();
}
public get selectionStart(): [number, number] { return this._model.finalSelectionStart; }
@@ -237,7 +238,7 @@ export class SelectionManager extends EventEmitter {
// and joining the array into a multi-line string.
const formattedResult = result.map(line => {
return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' ');
}).join('\n');
}).join(Browser.isMSWindows ? '\r\n' : '\n');
return formattedResult;
}
+23
View File
@@ -13,6 +13,7 @@ export class Viewport {
private currentRowHeight: number;
private lastRecordedBufferLength: number;
private lastRecordedViewportHeight: number;
private lastTouchY: number;
/**
* Creates a new Viewport.
@@ -121,4 +122,26 @@ export class Viewport {
// Prevent the page from scrolling when the terminal scrolls
ev.preventDefault();
};
/**
* Handles the touchstart event, recording the touch occurred.
* @param ev The touch event.
*/
public onTouchStart(ev: TouchEvent) {
this.lastTouchY = ev.touches[0].pageY;
};
/**
* Handles the touchmove event, scrolling the viewport if the position shifted.
* @param ev The touch event.
*/
public onTouchMove(ev: TouchEvent) {
let deltaY = this.lastTouchY - ev.touches[0].pageY;
this.lastTouchY = ev.touches[0].pageY;
if (deltaY === 0) {
return;
}
this.viewportElement.scrollTop += deltaY;
ev.preventDefault();
};
}
+5
View File
@@ -55,6 +55,11 @@ describe('xterm.js', function() {
it('should throw when setting a non-existant option', function() {
assert.throws(xterm.setOption.bind(xterm, 'fake', true));
});
it('should not allow scrollback less than number of rows', function() {
let setOptionCall = xterm.setOption.bind(xterm, 'scrollback', xterm.rows - 1);
assert.equal(setOptionCall(), false);
});
});
describe('clear', function() {
+8 -10
View File
@@ -7,21 +7,19 @@ import { ICharMeasure, ITerminal } from '../Interfaces';
import { CharMeasure } from './CharMeasure';
describe('CharMeasure', () => {
let dom: jsdom.JSDOM;
let window: Window;
let document: Document;
let container: HTMLElement;
let charMeasure: ICharMeasure;
beforeEach(done => {
jsdom.env('', (err, w) => {
window = w;
document = window.document;
container = document.createElement('div');
document.body.appendChild(container);
charMeasure = new CharMeasure(document, container);
done();
});
beforeEach(() => {
dom = new jsdom.JSDOM('');
window = dom.window;
document = window.document;
container = document.createElement('div');
document.body.appendChild(container);
charMeasure = new CharMeasure(document, container);
});
describe('measure', () => {
+48 -24
View File
@@ -420,6 +420,15 @@ Terminal.prototype.setOption = function(key, value) {
}
switch (key) {
case 'scrollback':
if (value < this.rows) {
let msg = 'Setting the scrollback value less than the number of rows ';
msg += `(${this.rows}) is not allowed.`;
console.warn(msg);
return false;
}
if (this.options[key] !== value) {
if (this.lines.length > value) {
const amountToTrim = this.lines.length - value;
@@ -653,7 +662,6 @@ Terminal.prototype.open = function(parent, focus) {
this.element.classList.add('xterm-theme-' + this.theme);
this.setCursorBlinking(this.options.cursorBlink);
this.element.style.height;
this.element.setAttribute('tabindex', 0);
this.viewportElement = document.createElement('div');
@@ -1088,6 +1096,18 @@ Terminal.prototype.bindMouse = function() {
self.viewport.onWheel(ev);
return self.cancel(ev);
});
on(el, 'touchstart', function(ev) {
if (self.mouseEvents) return;
self.viewport.onTouchStart(ev);
return self.cancel(ev);
});
on(el, 'touchmove', function(ev) {
if (self.mouseEvents) return;
self.viewport.onTouchMove(ev);
return self.cancel(ev);
});
};
/**
@@ -1128,7 +1148,7 @@ Terminal.prototype.queueLinkification = function(start, end) {
this.linkifier.linkifyRow(i);
}
}
}
};
/**
* Display the cursor element
@@ -1239,25 +1259,25 @@ Terminal.prototype.scrollDisp = function(disp, suppressScrollEvent) {
*/
Terminal.prototype.scrollPages = function(pageCount) {
this.scrollDisp(pageCount * (this.rows - 1));
}
};
/**
* Scrolls the display of the terminal to the top.
*/
Terminal.prototype.scrollToTop = function() {
this.scrollDisp(-this.ydisp);
}
};
/**
* Scrolls the display of the terminal to the bottom.
*/
Terminal.prototype.scrollToBottom = function() {
this.scrollDisp(this.ybase - this.ydisp);
}
};
/**
* Writes text to the terminal.
* @param {string} text The text to write to the terminal.
* @param {string} data The text to write to the terminal.
*/
Terminal.prototype.write = function(data) {
this.writeBuffer.push(data);
@@ -1281,7 +1301,7 @@ Terminal.prototype.write = function(data) {
self.innerWrite();
});
}
}
};
Terminal.prototype.innerWrite = function() {
var writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE);
@@ -1323,7 +1343,7 @@ Terminal.prototype.innerWrite = function() {
/**
* Writes text to the terminal, followed by a break line character (\n).
* @param {string} text The text to write to the terminal.
* @param {string} data The text to write to the terminal.
*/
Terminal.prototype.writeln = function(data) {
this.write(data + '\r\n');
@@ -1339,25 +1359,25 @@ Terminal.prototype.attachCustomKeydownHandler = function(customKeydownHandler) {
let message = 'attachCustomKeydownHandler() is DEPRECATED and will be removed soon. Please use attachCustomKeyEventHandler() instead.';
console.warn(message);
this.attachCustomKeyEventHandler(customKeydownHandler);
}
};
/**
* Attaches a custom key event handler which is run before keys are processed, giving consumers of
* xterm.js ultimate control as to what keys should be processed by the terminal and what keys
* should not.
* @param {function} customKeypressHandler The custom KeyboardEvent handler to attach. This is a
* @param {function} customKeyEventHandler The custom KeyboardEvent handler to attach. This is a
* function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent
* the default action. The function returns whether the event should be processed by xterm.js.
*/
Terminal.prototype.attachCustomKeyEventHandler = function(customKeyEventHandler) {
this.customKeyEventHandler = customKeyEventHandler;
}
};
/**
* Attaches a http(s) link handler, forcing web links to behave differently to
* regular <a> tags. This will trigger a refresh as links potentially need to be
* reconstructed. Calling this with null will remove the handler.
* @param {LinkHandler} handler The handler callback function.
* @param {LinkMatcherHandler} handler The handler callback function.
*/
Terminal.prototype.setHypertextLinkHandler = function(handler) {
if (!this.linkifier) {
@@ -1366,7 +1386,7 @@ Terminal.prototype.setHypertextLinkHandler = function(handler) {
this.linkifier.setHypertextLinkHandler(handler);
// Refresh to force links to refresh
this.refresh(0, this.rows - 1);
}
};
/**
* Attaches a validation callback for hypertext links. This is useful to use
@@ -1374,14 +1394,14 @@ Terminal.prototype.setHypertextLinkHandler = function(handler) {
* @param {LinkMatcherValidationCallback} callback The callback to use, this can
* be cleared with null.
*/
Terminal.prototype.setHypertextValidationCallback = function(handler) {
Terminal.prototype.setHypertextValidationCallback = function(callback) {
if (!this.linkifier) {
throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called');
}
this.linkifier.setHypertextValidationCallback(handler);
this.linkifier.setHypertextValidationCallback(callback);
// Refresh to force links to refresh
this.refresh(0, this.rows - 1);
}
};
/**
* Registers a link matcher, allowing custom link patterns to be matched and
@@ -1389,7 +1409,7 @@ Terminal.prototype.setHypertextValidationCallback = function(handler) {
* @param {RegExp} regex The regular expression to search for, specifically
* this searches the textContent of the rows. You will want to use \s to match
* a space ' ' character for example.
* @param {LinkHandler} handler The callback when the link is called.
* @param {LinkMatcherHandler} handler The callback when the link is called.
* @param {LinkMatcherOptions} [options] Options for the link matcher.
* @return {number} The ID of the new matcher, this can be used to deregister.
*/
@@ -1399,7 +1419,7 @@ Terminal.prototype.registerLinkMatcher = function(regex, handler, options) {
this.refresh(0, this.rows - 1);
return matcherId;
}
}
};
/**
* Deregisters a link matcher if it has been registered.
@@ -1411,14 +1431,14 @@ Terminal.prototype.deregisterLinkMatcher = function(matcherId) {
this.refresh(0, this.rows - 1);
}
}
}
};
/**
* Gets whether the terminal has an active selection.
*/
Terminal.prototype.hasSelection = function() {
return this.selectionManager.hasSelection;
}
};
/**
* Gets the terminal's current selection, this is useful for implementing copy
@@ -1426,21 +1446,21 @@ Terminal.prototype.hasSelection = function() {
*/
Terminal.prototype.getSelection = function() {
return this.selectionManager.selectionText;
}
};
/**
* Clears the current terminal selection.
*/
Terminal.prototype.clearSelection = function() {
this.selectionManager.clearSelection();
}
};
/**
* Selects all text within the terminal.
*/
Terminal.prototype.selectAll = function() {
this.selectionManager.selectAll();
}
};
/**
* Handle a keydown event
@@ -1908,6 +1928,10 @@ Terminal.prototype.resize = function(x, y) {
return;
}
if (y > this.getOption('scrollback')) {
this.setOption('scrollback', y)
}
var line
, el
, i
@@ -1949,7 +1973,7 @@ Terminal.prototype.resize = function(x, y) {
// There is room above the buffer and there are no empty elements below the line,
// scroll up
this.ybase--;
addToY++
addToY++;
if (this.ydisp > 0) {
// Viewport is at the top of the buffer, must increase downwards
this.ydisp--;