diff --git a/README.md b/README.md
index b9b4c1777..730fc9af9 100644
--- a/README.md
+++ b/README.md
@@ -123,6 +123,8 @@ computational environment for Jupyter, supporting interactive data science and s
- [**Azure Cloud Shell**](https://shell.azure.com): Azure Cloud Shell is a Microsoft-managed admin machine built on Azure, for Azure.
- [**atom-xterm**](https://atom.io/packages/atom-xterm): Atom plugin for providing terminals inside your Atom workspace.
- [**rtty**](https://github.com/zhaojh329/rtty): A reverse proxy WebTTY. It is composed of the client and the server.
+- [**Pisth**](https://github.com/ColdGrub1384/Pisth): An SFTP and SSH client for iOS
+- [**abstruse**](https://github.com/bleenco/abstruse): Abstruse CI is a continuous integration platform based on Node.JS and Docker.
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list.
@@ -164,6 +166,10 @@ Xterm.js is maintained by [SourceLair](https://www.sourcelair.com/) and a few ex
To contribute either code, documentation or issues to xterm.js please read the [Contributing document](CONTRIBUTING.md) beforehand. The development of xterm.js does not require any special tool. All you need is an editor that supports JavaScript/TypeScript and a browser. You will need Node.js installed locally to get all the features working in the demo.
+### Code structure
+
+`src/` is roughly split up into areas of functionality such as `renderer/` that handles all rendering and `utils/` which provides general utility functions. The `shared/` folder contains code that can be used from either the main thread or a web worker thread, all code inside a `shared/` folder should only ever import other code from a `shared/` folder to minimize the amount of code run what launching a web worker.
+
## License Agreement
If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
diff --git a/demo/index.html b/demo/index.html
index 93399f9cd..da348f5e6 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -23,6 +23,9 @@
cursorBlink
+
+ macOptionIsMeta
+
cursorStyle
diff --git a/demo/main.js b/demo/main.js
index 95b15a0db..1faf77d8a 100644
--- a/demo/main.js
+++ b/demo/main.js
@@ -27,6 +27,7 @@ var terminalContainer = document.getElementById('terminal-container'),
optionElements = {
cursorBlink: document.querySelector('#option-cursor-blink'),
cursorStyle: document.querySelector('#option-cursor-style'),
+ macOptionIsMeta: document.querySelector('#option-mac-option-is-meta'),
scrollback: document.querySelector('#option-scrollback'),
tabstopwidth: document.querySelector('#option-tabstopwidth'),
bellStyle: document.querySelector('#option-bell-style')
@@ -72,6 +73,9 @@ optionElements.cursorStyle.addEventListener('change', function () {
optionElements.bellStyle.addEventListener('change', function () {
term.setOption('bellStyle', optionElements.bellStyle.value);
});
+optionElements.macOptionIsMeta.addEventListener('change', function () {
+ term.setOption('macOptionIsMeta', optionElements.macOptionIsMeta.checked);
+});
optionElements.scrollback.addEventListener('change', function () {
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
});
@@ -87,6 +91,7 @@ function createTerminal() {
terminalContainer.removeChild(terminalContainer.children[0]);
}
term = new Terminal({
+ macOptionIsMeta: optionElements.macOptionIsMeta.enabled,
cursorBlink: optionElements.cursorBlink.checked,
scrollback: parseInt(optionElements.scrollback.value, 10),
tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts
index 5a5f6c501..6761dcd54 100644
--- a/fixtures/typings-test/typings-test.ts
+++ b/fixtures/typings-test/typings-test.ts
@@ -144,6 +144,9 @@ namespace methods_core {
const r20: string = t.getOption('bellStyle');
const r21: boolean = t.getOption('enableBold');
const r22: number = t.getOption('letterSpacing');
+ const r23: boolean = t.getOption('macOptionIsMeta');
+ const r24: string = t.getOption('fontWeight');
+ const r25: string = t.getOption('fontWeightBold');
}
{
const t: Terminal = new Terminal();
@@ -157,6 +160,10 @@ namespace methods_core {
t.setOption('debug', true);
t.setOption('disableStdin', true);
t.setOption('enableBold', true);
+ t.setOption('fontWeight', 'normal');
+ t.setOption('fontWeight', 'bold');
+ t.setOption('fontWeightBold', 'normal');
+ t.setOption('fontWeightBold', 'bold');
t.setOption('popOnBell', true);
t.setOption('screenKeys', true);
t.setOption('useFlowControl', true);
@@ -177,6 +184,7 @@ namespace methods_core {
t.setOption('lineHeight', 1);
t.setOption('fontFamily', 'foo');
t.setOption('theme', {background: '#ff0000'});
+ t.setOption('macOptionIsMeta', true);
}
}
namespace scrolling {
diff --git a/package.json b/package.json
index 6b1eb2302..cf3df57be 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
- "version": "3.0.0",
+ "version": "3.1.0-master",
"ignore": [
"demo",
"test",
diff --git a/src/Buffer.ts b/src/Buffer.ts
index f8610ea78..82e524e94 100644
--- a/src/Buffer.ts
+++ b/src/Buffer.ts
@@ -120,11 +120,6 @@ export class Buffer implements IBuffer {
if (this._terminal.cols < newCols) {
const ch: CharData = [this._terminal.defAttr, ' ', 1, 32]; // does xterm use the default attr?
for (let i = 0; i < this._lines.length; i++) {
- // TODO: This should be removed, with tests setup for the case that was
- // causing the underlying bug, see https://github.com/sourcelair/xterm.js/issues/824
- if (this._lines.get(i) === undefined) {
- this._lines.set(i, this._terminal.blankLine(undefined, undefined, newCols));
- }
while (this._lines.get(i).length < newCols) {
this._lines.get(i).push(ch);
}
@@ -181,16 +176,13 @@ export class Buffer implements IBuffer {
}
// Make sure that the cursor stays on screen
- if (this.y >= newRows) {
- this.y = newRows - 1;
- }
+ this.x = Math.min(this.x, newCols - 1);
+ this.y = Math.min(this.y, newRows - 1);
if (addToY) {
this.y += addToY;
}
-
- if (this.x >= newCols) {
- this.x = newCols - 1;
- }
+ this.savedY = Math.min(this.savedY, newRows - 1);
+ this.savedX = Math.min(this.savedX, newCols - 1);
this.scrollTop = 0;
}
diff --git a/src/BufferSet.ts b/src/BufferSet.ts
index eb6f4507b..01af2a7bc 100644
--- a/src/BufferSet.ts
+++ b/src/BufferSet.ts
@@ -61,24 +61,35 @@ export class BufferSet extends EventEmitter implements IBufferSet {
* Sets the normal Buffer of the BufferSet as its currently active Buffer
*/
public activateNormalBuffer(): void {
+ if (this._activeBuffer === this._normal) {
+ return;
+ }
// The alt buffer should always be cleared when we switch to the normal
// buffer. This frees up memory since the alt buffer should always be new
// when activated.
this._alt.clear();
-
this._activeBuffer = this._normal;
- this.emit('activate', this._normal);
+ this.emit('activate', {
+ activeBuffer: this._normal,
+ inactiveBuffer: this._alt
+ });
}
/**
* Sets the alt Buffer of the BufferSet as its currently active Buffer
*/
public activateAltBuffer(): void {
+ if (this._activeBuffer === this._alt) {
+ return;
+ }
// Since the alt buffer is always cleared when the normal buffer is
// activated, we want to fill it when switching to it.
this._alt.fillViewportRows();
this._activeBuffer = this._alt;
- this.emit('activate', this._alt);
+ this.emit('activate', {
+ activeBuffer: this._alt,
+ inactiveBuffer: this._normal
+ });
}
/**
diff --git a/src/InputHandler.ts b/src/InputHandler.ts
index 42b89543d..4fc14bd93 100644
--- a/src/InputHandler.ts
+++ b/src/InputHandler.ts
@@ -928,7 +928,6 @@ export class InputHandler implements IInputHandler {
case 47: // alt screen buffer
case 1047: // alt screen buffer
this._terminal.buffers.activateAltBuffer();
- this._terminal.selectionManager.setBuffer(this._terminal.buffer);
this._terminal.viewport.syncScrollArea();
this._terminal.showCursor();
break;
@@ -1100,7 +1099,6 @@ export class InputHandler implements IInputHandler {
// if (params[0] === 1049) {
// this.restoreCursor(params);
// }
- this._terminal.selectionManager.setBuffer(this._terminal.buffer);
this._terminal.refresh(0, this._terminal.rows - 1);
this._terminal.viewport.syncScrollArea();
this._terminal.showCursor();
diff --git a/src/Interfaces.ts b/src/Interfaces.ts
index b639d5a3d..4ecc87f60 100644
--- a/src/Interfaces.ts
+++ b/src/Interfaces.ts
@@ -7,8 +7,6 @@ import { IEventEmitter } from 'xterm';
import { ITerminalOptions, ILinkMatcherOptions, IMouseZoneManager, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, IColorSet, IRenderer, IBufferSet, IBuffer, ISelectionManager } from '../typings/xterm-internal';
import { ICharset } from './Interfaces';
-
-
/**
* This interface encapsulates everything needed from the Terminal by the
* InputHandler. This cleanly separates the large amount of methods needed by
diff --git a/src/Linkifier.ts b/src/Linkifier.ts
index 5d601fce7..64d7510c5 100644
--- a/src/Linkifier.ts
+++ b/src/Linkifier.ts
@@ -82,12 +82,12 @@ export class Linkifier extends EventEmitter implements ILinkifier {
}
// Increase range to linkify
- if (!this._rowsToLinkify.start) {
+ if (this._rowsToLinkify.start === null) {
this._rowsToLinkify.start = start;
this._rowsToLinkify.end = end;
} else {
- this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start;
- this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end;
+ this._rowsToLinkify.start = Math.min(this._rowsToLinkify.start, start);
+ this._rowsToLinkify.end = Math.max(this._rowsToLinkify.end, end);
}
// Clear out any existing links on this row range
diff --git a/src/SelectionManager.test.ts b/src/SelectionManager.test.ts
index 08f2d9814..4662c8a15 100644
--- a/src/SelectionManager.test.ts
+++ b/src/SelectionManager.test.ts
@@ -20,10 +20,9 @@ class TestMockTerminal extends MockTerminal {
class TestSelectionManager extends SelectionManager {
constructor(
terminal: ITerminal,
- buffer: IBuffer,
charMeasure: CharMeasure
) {
- super(terminal, buffer, charMeasure);
+ super(terminal, charMeasure);
}
public get model(): SelectionModel { return this._model; }
@@ -58,7 +57,7 @@ describe('SelectionManager', () => {
terminal.buffers = new BufferSet(terminal);
terminal.buffer = terminal.buffers.active;
buffer = terminal.buffer;
- selectionManager = new TestSelectionManager(terminal, buffer, null);
+ selectionManager = new TestSelectionManager(terminal, null);
});
function stringToRow(text: string): LineData {
diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts
index 5061fd9d3..2b5b0fec7 100644
--- a/src/SelectionManager.ts
+++ b/src/SelectionManager.ts
@@ -5,7 +5,7 @@
import { ITerminal, ICircularList, ISelectionManager, IBuffer, LineData, CharData } from '../typings/xterm-internal';
import { MouseHelper } from './utils/MouseHelper';
-import * as Browser from './utils/Browser';
+import * as Browser from './shared/utils/Browser';
import { CharMeasure } from './utils/CharMeasure';
import { CircularList } from './utils/CircularList';
import { EventEmitter } from './EventEmitter';
@@ -94,10 +94,10 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
private _mouseMoveListener: EventListener;
private _mouseUpListener: EventListener;
+ private _trimListener: (...args: any[]) => void;
constructor(
private _terminal: ITerminal,
- private _buffer: IBuffer,
private _charMeasure: CharMeasure
) {
super();
@@ -108,18 +108,24 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
this._activeSelectionMode = SelectionMode.NORMAL;
}
+ private get _buffer(): IBuffer {
+ return this._terminal.buffers.active;
+ }
+
/**
* Initializes listener variables.
*/
private _initListeners(): void {
this._mouseMoveListener = event => this._onMouseMove(event);
this._mouseUpListener = event => this._onMouseUp(event);
+ this._trimListener = (amount: number) => this._onTrim(amount);
- // Only adjust the selection on trim, shiftElements is rarely used (only in
- // reverseIndex) and delete in a splice is only ever used when the same
- // number of elements was just added. Given this is could actually be
- // beneficial to leave the selection as is for these cases.
- this._buffer.lines.on('trim', (amount: number) => this._onTrim(amount));
+ this.initBuffersListeners();
+ }
+
+ public initBuffersListeners(): void {
+ this._terminal.buffer.lines.on('trim', this._trimListener);
+ this._terminal.buffers.on('activate', e => this._onBufferActivate(e));
}
/**
@@ -138,16 +144,6 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
this._enabled = true;
}
- /**
- * Sets the active buffer, this should be called when the alt buffer is
- * switched in or out.
- * @param buffer The active buffer.
- */
- public setBuffer(buffer: IBuffer): void {
- this._buffer = buffer;
- this.clearSelection();
- }
-
public get selectionStart(): [number, number] { return this._model.finalSelectionStart; }
public get selectionEnd(): [number, number] { return this._model.finalSelectionEnd; }
@@ -546,6 +542,16 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
this._terminal.emit('selection');
}
+ private _onBufferActivate(e: {activeBuffer: IBuffer, inactiveBuffer: IBuffer}): void {
+ this.clearSelection();
+ // Only adjust the selection on trim, shiftElements is rarely used (only in
+ // reverseIndex) and delete in a splice is only ever used when the same
+ // number of elements was just added. Given this is could actually be
+ // beneficial to leave the selection as is for these cases.
+ e.inactiveBuffer.lines.off('trim', this._trimListener);
+ e.activeBuffer.lines.on('trim', this._trimListener);
+ }
+
/**
* Converts a viewport column to the character index on the buffer line, the
* latter takes into account wide characters.
diff --git a/src/Terminal.test.ts b/src/Terminal.test.ts
index 9cb0b75c1..946e9efb1 100644
--- a/src/Terminal.test.ts
+++ b/src/Terminal.test.ts
@@ -503,6 +503,9 @@ describe('term.js addons', () => {
it('should return \\x1b[5C for alt+right', () => {
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C
});
+ it('should return \\x1ba for alt+a', () => {
+ assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 65 }).key, '\x1ba');
+ });
});
describe('On macOS platforms', () => {
@@ -515,6 +518,19 @@ describe('term.js addons', () => {
it('should return \\x1bf for alt+right', () => {
assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1bf'); // CSI 5 C
});
+ it('should return undefined for alt+a', () => {
+ assert.strictEqual(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 65 }).key, undefined);
+ });
+ });
+
+ describe('with macOptionIsMeta', () => {
+ beforeEach(() => {
+ term.browser.isMac = true;
+ term.setOption('macOptionIsMeta', true);
+ });
+ it('should return \\x1ba for alt+a', () => {
+ assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 65 }).key, '\x1ba');
+ });
});
it('should return \\x1b[5A for alt+up', () => {
@@ -597,6 +613,22 @@ describe('term.js addons', () => {
};
});
+ describe('with macOptionIsMeta', () => {
+ beforeEach(() => {
+ term.browser.isMac = true;
+ term.setOption('macOptionIsMeta', true);
+ });
+
+ it('should interfere with the alt key on keyDown', () => {
+ evKeyDown.altKey = true;
+ evKeyDown.keyCode = 81;
+ assert.equal(term.keyDown(evKeyDown), false);
+ evKeyDown.altKey = true;
+ evKeyDown.keyCode = 192;
+ assert.equal(term.keyDown(evKeyDown), false);
+ });
+ });
+
describe('On Mac OS', () => {
beforeEach(() => {
term.browser.isMac = true;
diff --git a/src/Terminal.ts b/src/Terminal.ts
index dbdd700b4..0c2ce7922 100644
--- a/src/Terminal.ts
+++ b/src/Terminal.ts
@@ -36,7 +36,7 @@ import { Renderer } from './renderer/Renderer';
import { Linkifier } from './Linkifier';
import { SelectionManager } from './SelectionManager';
import { CharMeasure } from './utils/CharMeasure';
-import * as Browser from './utils/Browser';
+import * as Browser from './shared/utils/Browser';
import { MouseHelper } from './utils/MouseHelper';
import { CHARSETS } from './Charsets';
import { CustomKeyEventHandler } from './Types';
@@ -44,7 +44,6 @@ import { ICharset, IInputHandlingTerminal, IViewport, ICompositionHelper } from
import { BELL_SOUND } from './utils/Sounds';
import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager';
import { MouseZoneManager } from './input/MouseZoneManager';
-import { initialize as initializeCharAtlas } from './renderer/CharAtlas';
// Let it work inside Node.js for automated testing purposes.
const document = (typeof window !== 'undefined') ? window.document : null;
@@ -74,11 +73,14 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
enableBold: true,
fontFamily: 'courier-new, courier, monospace',
fontSize: 15,
+ fontWeight: 'normal',
+ fontWeightBold: 'bold',
lineHeight: 1.0,
letterSpacing: 0,
scrollback: 1000,
screenKeys: false,
debug: false,
+ macOptionIsMeta: false,
cancelEvents: false,
disableStdin: false,
useFlowControl: false,
@@ -191,7 +193,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
public selectionManager: SelectionManager;
public linkifier: ILinkifier;
public buffers: BufferSet;
- public buffer: Buffer;
public viewport: IViewport;
private compositionHelper: ICompositionHelper;
public charMeasure: CharMeasure;
@@ -292,17 +293,19 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
// Create the terminal's buffers and set the current buffer
this.buffers = new BufferSet(this);
- this.buffer = this.buffers.active; // Convenience shortcut;
- this.buffers.on('activate', (buffer: Buffer) => {
- this.buffer = buffer;
- });
-
- // Ensure the selection manager has the correct buffer
if (this.selectionManager) {
- this.selectionManager.setBuffer(this.buffer);
+ this.selectionManager.clearSelection();
+ this.selectionManager.initBuffersListeners();
}
}
+ /**
+ * Convenience property to active buffer.
+ */
+ public get buffer(): Buffer {
+ return this.buffers.active;
+ }
+
/**
* back_color_erase feature for xterm.
*/
@@ -360,6 +363,16 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
value = 'block';
}
break;
+ case 'fontWeight':
+ if (!value) {
+ value = 'normal';
+ }
+ break;
+ case 'fontWeightBold':
+ if (!value) {
+ value = 'bold';
+ }
+ break;
case 'lineHeight':
if (value < 1) {
console.warn(`${key} cannot be less than 1, value: ${value}`);
@@ -413,11 +426,14 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
case 'enableBold':
case 'letterSpacing':
case 'lineHeight':
+ case 'fontWeight':
+ case 'fontWeightBold':
+ const didCharSizeChange = (key === 'fontWeight' || key === 'fontWeightBold' || key === 'enableBold');
+
// When the font changes the size of the cells may change which requires a renderer clear
this.renderer.clear();
- this.renderer.onResize(this.cols, this.rows, false);
+ this.renderer.onResize(this.cols, this.rows, didCharSizeChange);
this.refresh(0, this.rows - 1);
- // this.charMeasure.measure(this.options);
case 'scrollback':
this.buffers.resize(this.cols, this.rows);
this.viewport.syncScrollArea();
@@ -573,8 +589,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.document = this.parent.ownerDocument;
this.body = this.document.body;
- initializeCharAtlas(this.document);
-
// Create main element container
this.element = this.document.createElement('div');
this.element.classList.add('terminal');
@@ -639,7 +653,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true));
this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea());
- this.selectionManager = new SelectionManager(this, this.buffer, this.charMeasure);
+ this.selectionManager = new SelectionManager(this, this.charMeasure);
this.element.addEventListener('mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e));
this.selectionManager.on('refresh', data => this.renderer.onSelectionChanged(data.start, data.end));
this.selectionManager.on('newselection', text => {
@@ -1372,7 +1386,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
return this.cancel(ev, true);
}
- if (isThirdLevelShift(this.browser, ev)) {
+ if (this._isThirdLevelShift(this.browser, ev)) {
return true;
}
@@ -1393,6 +1407,19 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
return this.cancel(ev, true);
}
+ private _isThirdLevelShift(browser: IBrowser, ev: KeyboardEvent): boolean {
+ const thirdLevelKey =
+ (browser.isMac && !this.options.macOptionIsMeta && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||
+ (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);
+
+ if (ev.type === 'keypress') {
+ return thirdLevelKey;
+ }
+
+ // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)
+ return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
+ }
+
/**
* Returns an object that determines how a KeyboardEvent should be handled. The key of the
* returned value is the new key code to pass to the PTY.
@@ -1697,8 +1724,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
// ^] - Operating System Command (OSC)
result.key = String.fromCharCode(29);
}
- } else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {
- // On Mac this is a third level shift. Use instead.
+ } else if ((!this.browser.isMac || this.options.macOptionIsMeta) && ev.altKey && !ev.ctrlKey && !ev.metaKey) {
+ // On macOS this is a third level shift when !macOptionIsMeta. Use instead.
if (ev.keyCode >= 65 && ev.keyCode <= 90) {
result.key = C0.ESC + String.fromCharCode(ev.keyCode + 32);
} else if (ev.keyCode === 192) {
@@ -1764,7 +1791,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
}
if (!key || (
- (ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this.browser, ev)
+ (ev.altKey || ev.ctrlKey || ev.metaKey) && !this._isThirdLevelShift(this.browser, ev)
)) {
return false;
}
@@ -2078,11 +2105,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.options.cols = this.cols;
const customKeyEventHandler = this.customKeyEventHandler;
const inputHandler = this.inputHandler;
- const buffers = this.buffers;
this.setup();
this.customKeyEventHandler = customKeyEventHandler;
this.inputHandler = inputHandler;
- this.buffers = buffers;
this.refresh(0, this.rows - 1);
this.viewport.syncScrollArea();
}
@@ -2160,19 +2185,6 @@ function off(el: any, type: string, handler: (event: Event) => any, capture: boo
el.removeEventListener(type, handler, capture);
}
-function isThirdLevelShift(browser: IBrowser, ev: KeyboardEvent): boolean {
- const thirdLevelKey =
- (browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||
- (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);
-
- if (ev.type === 'keypress') {
- return thirdLevelKey;
- }
-
- // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)
- return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
-}
-
function wasMondifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
return ev.keyCode === 16 || // Shift
ev.keyCode === 17 || // Ctrl
diff --git a/src/addons/attach/Intefaces.ts b/src/addons/attach/Interfaces.ts
similarity index 100%
rename from src/addons/attach/Intefaces.ts
rename to src/addons/attach/Interfaces.ts
diff --git a/src/addons/attach/attach.ts b/src/addons/attach/attach.ts
index d963a658f..cbfd4a248 100644
--- a/src/addons/attach/attach.ts
+++ b/src/addons/attach/attach.ts
@@ -8,7 +8,7 @@
///
import { Terminal } from 'xterm';
-import { IAttachAddonTerminal } from './Intefaces';
+import { IAttachAddonTerminal } from './Interfaces';
/**
* Attaches the given terminal to the given socket.
diff --git a/src/addons/search/SearchHelper.ts b/src/addons/search/SearchHelper.ts
index dd941682a..2abc3b38a 100644
--- a/src/addons/search/SearchHelper.ts
+++ b/src/addons/search/SearchHelper.ts
@@ -113,8 +113,23 @@ export class SearchHelper implements ISearchHelper {
private _findInLine(term: string, y: number): ISearchResult {
const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase();
const lowerTerm = term.toLowerCase();
- const searchIndex = lowerStringLine.indexOf(lowerTerm);
+ let searchIndex = lowerStringLine.indexOf(lowerTerm);
if (searchIndex >= 0) {
+ const line = this._terminal.buffer.lines.get(y);
+ for (let i = 0; i < searchIndex; i++) {
+ const charData = line[i];
+ // Adjust the searchIndex to normalize emoji into single chars
+ const char = charData[1/*CHAR_DATA_CHAR_INDEX*/];
+ if (char.length > 1) {
+ searchIndex -= char.length - 1;
+ }
+ // Adjust the searchIndex for empty characters following wide unicode
+ // chars (eg. CJK)
+ const charWidth = charData[2/*CHAR_DATA_WIDTH_INDEX*/];
+ if (charWidth === 0) {
+ searchIndex++;
+ }
+ }
return {
term,
col: searchIndex,
diff --git a/src/addons/terminado/Intefaces.ts b/src/addons/terminado/Interfaces.ts
similarity index 100%
rename from src/addons/terminado/Intefaces.ts
rename to src/addons/terminado/Interfaces.ts
diff --git a/src/addons/terminado/terminado.ts b/src/addons/terminado/terminado.ts
index d5cf72d1b..4acf9dd84 100644
--- a/src/addons/terminado/terminado.ts
+++ b/src/addons/terminado/terminado.ts
@@ -9,7 +9,7 @@
///
import { Terminal } from 'xterm';
-import { ITerminadoAddonTerminal } from './Intefaces';
+import { ITerminadoAddonTerminal } from './Interfaces';
/**
* Attaches the given terminal to the given socket.
diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts
index 299d8b6f1..3c1f52be6 100644
--- a/src/renderer/BaseRenderLayer.ts
+++ b/src/renderer/BaseRenderLayer.ts
@@ -200,7 +200,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
* @param color The color of the character.
*/
protected fillCharTrueColor(terminal: ITerminal, charData: CharData, x: number, y: number): void {
- this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;
+ this._ctx.font = this._getFont(terminal, false);
this._ctx.textBaseline = 'top';
this._clipRow(terminal, y);
this._ctx.fillText(
@@ -268,7 +268,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
charAtlasCellWidth,
this._scaledCharHeight);
} else {
- this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim);
+ this._drawUncachedChar(terminal, char, width, fg, x, y, bold && terminal.options.enableBold, dim);
}
// This draws the atlas (for debugging purposes)
// this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
@@ -288,10 +288,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
*/
private _drawUncachedChar(terminal: ITerminal, char: string, width: number, fg: number, x: number, y: number, bold: boolean, dim: boolean): void {
this._ctx.save();
- this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;
- if (bold && terminal.options.enableBold) {
- this._ctx.font = `bold ${this._ctx.font}`;
- }
+ this._ctx.font = this._getFont(terminal, bold);
this._ctx.textBaseline = 'top';
if (fg === INVERTED_DEFAULT_COLOR) {
@@ -331,5 +328,16 @@ export abstract class BaseRenderLayer implements IRenderLayer {
this._scaledCellHeight);
this._ctx.clip();
}
+
+ /**
+ * Gets the current font.
+ * @param terminal The terminal.
+ * @param isBold If we should use the bold fontWeight.
+ */
+ protected _getFont(terminal: ITerminal, isBold: boolean): string {
+ const fontWeight = isBold ? terminal.options.fontWeightBold : terminal.options.fontWeight;
+
+ return `${fontWeight} ${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;
+ }
}
diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts
index 3a7886ffe..274bcc8f0 100644
--- a/src/renderer/CharAtlas.ts
+++ b/src/renderer/CharAtlas.ts
@@ -4,13 +4,16 @@
*/
import { ITerminal, ITheme, IColorSet } from '../../typings/xterm-internal';
-import { isFirefox } from '../utils/Browser';
+import { isFirefox } from '../shared/utils/Browser';
+import { generateCharAtlas, ICharAtlasRequest } from '../shared/CharAtlasGenerator';
export const CHAR_ATLAS_CELL_SPACING = 1;
interface ICharAtlasConfig {
fontSize: number;
fontFamily: string;
+ fontWeight: string;
+ fontWeightBold: string;
scaledCharWidth: number;
scaledCharHeight: number;
colors: IColorSet;
@@ -62,8 +65,28 @@ export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet, scaledC
}
}
+ const canvasFactory = (width: number, height: number) => {
+ const canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ return canvas;
+ };
+
+ const charAtlasConfig: ICharAtlasRequest = {
+ scaledCharWidth,
+ scaledCharHeight,
+ fontSize: terminal.options.fontSize,
+ fontFamily: terminal.options.fontFamily,
+ fontWeight: terminal.options.fontWeight,
+ fontWeightBold: terminal.options.fontWeightBold,
+ background: colors.background,
+ foreground: colors.foreground,
+ ansiColors: colors.ansi,
+ devicePixelRatio: window.devicePixelRatio
+ };
+
const newEntry: ICharAtlasCacheEntry = {
- bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi),
+ bitmap: generateCharAtlas(window, canvasFactory, charAtlasConfig),
config: newConfig,
ownedBy: [terminal]
};
@@ -85,6 +108,8 @@ function generateConfig(scaledCharWidth: number, scaledCharHeight: number, termi
scaledCharHeight,
fontFamily: terminal.options.fontFamily,
fontSize: terminal.options.fontSize,
+ fontWeight: terminal.options.fontWeight,
+ fontWeightBold: terminal.options.fontWeightBold,
colors: clonedColors
};
}
@@ -97,125 +122,10 @@ function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {
}
return a.fontFamily === b.fontFamily &&
a.fontSize === b.fontSize &&
+ a.fontWeight === b.fontWeight &&
+ a.fontWeightBold === b.fontWeightBold &&
a.scaledCharWidth === b.scaledCharWidth &&
a.scaledCharHeight === b.scaledCharHeight &&
a.colors.foreground === b.colors.foreground &&
a.colors.background === b.colors.background;
}
-
-let generator: CharAtlasGenerator;
-
-/**
- * Initializes the char atlas generator.
- * @param document The document.
- */
-export function initialize(document: Document): void {
- if (!generator) {
- generator = new CharAtlasGenerator(document);
- }
-}
-
-class CharAtlasGenerator {
- private _canvas: HTMLCanvasElement;
- private _ctx: CanvasRenderingContext2D;
-
- constructor(private _document: Document) {
- this._canvas = this._document.createElement('canvas');
- this._ctx = this._canvas.getContext('2d', {alpha: false});
- this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
- }
-
- public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise {
- const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING;
- const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING;
- this._canvas.width = 255 * cellWidth;
- this._canvas.height = (/*default+default bold*/2 + /*0-15*/16) * cellHeight;
-
- this._ctx.fillStyle = background;
- this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
-
- this._ctx.save();
- this._ctx.fillStyle = foreground;
- this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`;
- this._ctx.textBaseline = 'top';
-
- // Default color
- for (let i = 0; i < 256; i++) {
- this._ctx.save();
- this._ctx.beginPath();
- this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);
- this._ctx.clip();
- this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0);
- this._ctx.restore();
- }
- // Default color bold
- this._ctx.save();
- this._ctx.font = `bold ${this._ctx.font}`;
- for (let i = 0; i < 256; i++) {
- this._ctx.save();
- this._ctx.beginPath();
- this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);
- this._ctx.clip();
- this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight);
- this._ctx.restore();
- }
- this._ctx.restore();
-
- // Colors 0-15
- this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`;
- for (let colorIndex = 0; colorIndex < 16; colorIndex++) {
- // colors 8-15 are bold
- if (colorIndex === 8) {
- this._ctx.font = `bold ${this._ctx.font}`;
- }
- const y = (colorIndex + 2) * cellHeight;
- // Draw ascii characters
- for (let i = 0; i < 256; i++) {
- this._ctx.save();
- this._ctx.beginPath();
- this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
- this._ctx.clip();
- this._ctx.fillStyle = ansiColors[colorIndex];
- this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y);
- this._ctx.restore();
- }
- }
- this._ctx.restore();
-
- // Support is patchy for createImageBitmap at the moment, pass a canvas back
- // if support is lacking as drawImage works there too. Firefox is also
- // included here as ImageBitmap appears both buggy and has horrible
- // performance (tested on v55).
- if (!('createImageBitmap' in window) || isFirefox) {
- // Regenerate canvas and context as they are now owned by the char atlas
- const result = this._canvas;
- this._canvas = this._document.createElement('canvas');
- this._ctx = this._canvas.getContext('2d');
- this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
- return result;
- }
-
- const charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height);
-
- // Remove the background color from the image so characters may overlap
- const r = parseInt(background.substr(1, 2), 16);
- const g = parseInt(background.substr(3, 2), 16);
- const b = parseInt(background.substr(5, 2), 16);
- this._clearColor(charAtlasImageData, r, g, b);
-
- const promise = window.createImageBitmap(charAtlasImageData);
- // Clear the rect while the promise is in progress
- this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
- return promise;
- }
-
- private _clearColor(imageData: ImageData, r: number, g: number, b: number): void {
- for (let offset = 0; offset < imageData.data.length; offset += 4) {
- if (imageData.data[offset] === r &&
- imageData.data[offset + 1] === g &&
- imageData.data[offset + 2] === b) {
- imageData.data[offset + 3] = 0;
- }
- }
- }
-}
diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts
index f8d6a5bb0..eebcc87c1 100644
--- a/src/renderer/TextRenderLayer.ts
+++ b/src/renderer/TextRenderLayer.ts
@@ -31,7 +31,7 @@ export class TextRenderLayer extends BaseRenderLayer {
super.resize(terminal, dim, charSizeChanged);
// Clear the character width cache if the font or width has changed
- const terminalFont = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`;
+ const terminalFont = this._getFont(terminal, false);
if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) {
this._characterWidth = dim.scaledCharWidth;
this._characterFont = terminalFont;
@@ -164,7 +164,7 @@ export class TextRenderLayer extends BaseRenderLayer {
this._ctx.save();
if (flags & FLAGS.BOLD) {
- this._ctx.font = `bold ${this._ctx.font}`;
+ this._ctx.font = this._getFont(terminal, true);
// Convert the FG color to the bold variant
if (fg < 8) {
fg += 8;
diff --git a/src/shared/CharAtlasGenerator.ts b/src/shared/CharAtlasGenerator.ts
new file mode 100644
index 000000000..9b895c9c3
--- /dev/null
+++ b/src/shared/CharAtlasGenerator.ts
@@ -0,0 +1,140 @@
+/**
+ * Copyright (c) 2018 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+import { isFirefox } from './utils/Browser';
+import { FontWeight } from './Types';
+
+declare const Promise: any;
+
+export interface IOffscreenCanvas {
+ width: number;
+ height: number;
+ getContext(type: '2d', config?: Canvas2DContextAttributes): CanvasRenderingContext2D;
+ transferToImageBitmap(): ImageBitmap;
+}
+
+export interface ICharAtlasRequest {
+ scaledCharWidth: number;
+ scaledCharHeight: number;
+ fontSize: number;
+ fontFamily: string;
+ fontWeight: FontWeight;
+ fontWeightBold: FontWeight;
+ background: string;
+ foreground: string;
+ ansiColors: string[];
+ devicePixelRatio: number;
+}
+
+export const CHAR_ATLAS_CELL_SPACING = 1;
+
+/**
+ * Generates a char atlas.
+ * @param context The window or worker context.
+ * @param canvasFactory A function to generate a canvas with a width or height.
+ * @param request The config for the new char atlas.
+ */
+export function generateCharAtlas(context: Window, canvasFactory: (width: number, height: number) => HTMLCanvasElement | IOffscreenCanvas, request: ICharAtlasRequest): HTMLCanvasElement | Promise {
+ const cellWidth = request.scaledCharWidth + CHAR_ATLAS_CELL_SPACING;
+ const cellHeight = request.scaledCharHeight + CHAR_ATLAS_CELL_SPACING;
+ const canvas = canvasFactory(
+ /*255 ascii chars*/255 * cellWidth,
+ (/*default+default bold*/2 + /*0-15*/16) * cellHeight
+ );
+ const ctx = canvas.getContext('2d', {alpha: false});
+
+ ctx.fillStyle = request.background;
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+ ctx.save();
+ ctx.fillStyle = request.foreground;
+ ctx.font = getFont(request.fontWeight, request);
+ ctx.textBaseline = 'top';
+
+ // Default color
+ for (let i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, 0, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, 0);
+ ctx.restore();
+ }
+ // Default color bold
+ ctx.save();
+ ctx.font = getFont(request.fontWeightBold, request);
+ for (let i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight);
+ ctx.restore();
+ }
+ ctx.restore();
+
+ // Colors 0-15
+ ctx.font = getFont(request.fontWeight, request);
+ for (let colorIndex = 0; colorIndex < 16; colorIndex++) {
+ // colors 8-15 are bold
+ if (colorIndex === 8) {
+ ctx.font = getFont(request.fontWeightBold, request);
+ }
+ const y = (colorIndex + 2) * cellHeight;
+ // Draw ascii characters
+ for (let i = 0; i < 256; i++) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(i * cellWidth, y, cellWidth, cellHeight);
+ ctx.clip();
+ ctx.fillStyle = request.ansiColors[colorIndex];
+ ctx.fillText(String.fromCharCode(i), i * cellWidth, y);
+ ctx.restore();
+ }
+ }
+ ctx.restore();
+
+ // Support is patchy for createImageBitmap at the moment, pass a canvas back
+ // if support is lacking as drawImage works there too. Firefox is also
+ // included here as ImageBitmap appears both buggy and has horrible
+ // performance (tested on v55).
+ if (!('createImageBitmap' in context) || isFirefox) {
+ // Don't attempt to clear background colors if createImageBitmap is not supported
+ if (canvas instanceof HTMLCanvasElement) {
+ // Just return the HTMLCanvas if it's a HTMLCanvasElement
+ return canvas;
+ } else {
+ // Transfer to an ImageBitmap is this is an OffscreenCanvas
+ return new Promise(r => r(canvas.transferToImageBitmap()));
+ }
+ }
+
+ const charAtlasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
+
+ // Remove the background color from the image so characters may overlap
+ const r = parseInt(request.background.substr(1, 2), 16);
+ const g = parseInt(request.background.substr(3, 2), 16);
+ const b = parseInt(request.background.substr(5, 2), 16);
+ clearColor(charAtlasImageData, r, g, b);
+
+ return context.createImageBitmap(charAtlasImageData);
+}
+
+/**
+ * Makes a partiicular rgb color in an ImageData completely transparent.
+ */
+function clearColor(imageData: ImageData, r: number, g: number, b: number): void {
+ for (let offset = 0; offset < imageData.data.length; offset += 4) {
+ if (imageData.data[offset] === r &&
+ imageData.data[offset + 1] === g &&
+ imageData.data[offset + 2] === b) {
+ imageData.data[offset + 3] = 0;
+ }
+ }
+}
+
+function getFont(fontWeight: FontWeight, request: ICharAtlasRequest): string {
+ return `${fontWeight} ${request.fontSize * request.devicePixelRatio}px ${request.fontFamily}`;
+}
diff --git a/src/shared/Types.ts b/src/shared/Types.ts
new file mode 100644
index 000000000..b61525bd4
--- /dev/null
+++ b/src/shared/Types.ts
@@ -0,0 +1,6 @@
+/**
+ * Copyright (c) 2018 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+ export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
diff --git a/src/utils/Browser.ts b/src/shared/utils/Browser.ts
similarity index 75%
rename from src/utils/Browser.ts
rename to src/shared/utils/Browser.ts
index 48c0c3748..1d4774d21 100644
--- a/src/utils/Browser.ts
+++ b/src/shared/utils/Browser.ts
@@ -3,8 +3,6 @@
* @license MIT
*/
-import { contains } from './Generic';
-
const isNode = (typeof navigator === 'undefined') ? true : false;
const userAgent = (isNode) ? 'node' : navigator.userAgent;
const platform = (isNode) ? 'node' : navigator.platform;
@@ -20,3 +18,12 @@ export const isIpad = platform === 'iPad';
export const isIphone = platform === 'iPhone';
export const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
export const isLinux = platform.indexOf('Linux') >= 0;
+
+/**
+ * Return if the given array contains the given element
+ * @param {Array} array The array to search for the given element.
+ * @param {Object} el The element to look for into the array
+ */
+export function contains(arr: any[], el: any): boolean {
+ return arr.indexOf(el) >= 0;
+};
diff --git a/src/utils/Generic.ts b/src/utils/Generic.ts
deleted file mode 100644
index 4bc6c487f..000000000
--- a/src/utils/Generic.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Copyright (c) 2016 The xterm.js authors. All rights reserved.
- * @license MIT
- */
-
-/**
- * Return if the given array contains the given element
- * @param {Array} array The array to search for the given element.
- * @param {Object} el The element to look for into the array
- */
-export function contains(arr: any[], el: any): boolean {
- return arr.indexOf(el) >= 0;
-}
diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts
index 34f3ced8b..64c326d55 100644
--- a/src/utils/TestUtils.test.ts
+++ b/src/utils/TestUtils.test.ts
@@ -5,9 +5,8 @@
import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ITheme, ILinkifier, IMouseHelper, ILinkMatcherOptions, LineData, IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../../typings/xterm-internal';
import { IInputHandlingTerminal, IViewport, ICompositionHelper } from '../Interfaces';
-import { } from '../Types';
import { Buffer } from '../Buffer';
-import * as Browser from './Browser';
+import * as Browser from '../shared/utils/Browser';
export class MockTerminal implements ITerminal {
getOption(key: any): any {
diff --git a/typings/xterm-internal.d.ts b/typings/xterm-internal.d.ts
index eca7fe334..3670bad06 100644
--- a/typings/xterm-internal.d.ts
+++ b/typings/xterm-internal.d.ts
@@ -92,7 +92,7 @@ export interface IBuffer {
prevStop(x?: number): number;
}
-export interface IBufferSet {
+export interface IBufferSet extends IEventEmitter {
alt: IBuffer;
normal: IBuffer;
active: IBuffer;
@@ -122,7 +122,6 @@ export interface ISelectionManager {
disable(): void;
enable(): void;
- setBuffer(buffer: IBuffer): void;
setSelection(row: number, col: number, length: number): void;
}
diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts
index 26aa5e0ed..dbd1eebc6 100644
--- a/typings/xterm.d.ts
+++ b/typings/xterm.d.ts
@@ -8,6 +8,11 @@
*/
declare module 'xterm' {
+ /**
+ * A string representing text font weight.
+ */
+ export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
+
/**
* An object containing start up options for the terminal.
*/
@@ -57,6 +62,16 @@ declare module 'xterm' {
*/
fontFamily?: string;
+ /**
+ * The font weight used to render non-bold text.
+ */
+ fontWeight?: FontWeight;
+
+ /**
+ * The font weight used to render bold text.
+ */
+ fontWeightBold?: FontWeight;
+
/**
* The spacing in whole pixels between characters..
*/
@@ -67,6 +82,11 @@ declare module 'xterm' {
*/
lineHeight?: number;
+ /**
+ * Whether to treat option as the meta key.
+ */
+ macOptionIsMeta?: boolean;
+
/**
* The number of rows in the terminal.
*/
@@ -396,12 +416,12 @@ declare module 'xterm' {
* Retrieves an option's value from the terminal.
* @param key The option key.
*/
- getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'termName'): string;
+ getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold'| 'termName'): string;
/**
* Retrieves an option's value from the terminal.
* @param key The option key.
*/
- getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean;
+ getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean;
/**
* Retrieves an option's value from the terminal.
* @param key The option key.
@@ -429,6 +449,12 @@ declare module 'xterm' {
* @param value The option value.
*/
setOption(key: 'fontFamily' | 'termName' | 'bellSound', value: string): void;
+ /**
+ * Sets an option on the terminal.
+ * @param key The option key.
+ * @param value The option value.
+ */
+ setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void;
/**
* Sets an option on the terminal.
* @param key The option key.
@@ -446,7 +472,7 @@ declare module 'xterm' {
* @param key The option key.
* @param value The option value.
*/
- setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void;
+ setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void;
/**
* Sets an option on the terminal.
* @param key The option key.