mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into 1103_search_wide_emoji
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
|
||||||
node_js:
|
node_js:
|
||||||
- 6
|
- 6
|
||||||
before_install:
|
before_install:
|
||||||
|
|||||||
@@ -120,6 +120,11 @@ computational environment for Jupyter, supporting interactive data science and s
|
|||||||
- [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React.
|
- [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React.
|
||||||
- [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm.
|
- [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm.
|
||||||
- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters.
|
- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters.
|
||||||
|
- [**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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
<p>
|
<p>
|
||||||
<label><input type="checkbox" id="option-cursor-blink"> cursorBlink</label>
|
<label><input type="checkbox" id="option-cursor-blink"> cursorBlink</label>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<label><input type="checkbox" id="option-mac-option-is-meta"> macOptionIsMeta</label>
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>
|
<label>
|
||||||
cursorStyle
|
cursorStyle
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ var terminalContainer = document.getElementById('terminal-container'),
|
|||||||
optionElements = {
|
optionElements = {
|
||||||
cursorBlink: document.querySelector('#option-cursor-blink'),
|
cursorBlink: document.querySelector('#option-cursor-blink'),
|
||||||
cursorStyle: document.querySelector('#option-cursor-style'),
|
cursorStyle: document.querySelector('#option-cursor-style'),
|
||||||
|
macOptionIsMeta: document.querySelector('#option-mac-option-is-meta'),
|
||||||
scrollback: document.querySelector('#option-scrollback'),
|
scrollback: document.querySelector('#option-scrollback'),
|
||||||
tabstopwidth: document.querySelector('#option-tabstopwidth'),
|
tabstopwidth: document.querySelector('#option-tabstopwidth'),
|
||||||
bellStyle: document.querySelector('#option-bell-style')
|
bellStyle: document.querySelector('#option-bell-style')
|
||||||
@@ -72,6 +73,9 @@ optionElements.cursorStyle.addEventListener('change', function () {
|
|||||||
optionElements.bellStyle.addEventListener('change', function () {
|
optionElements.bellStyle.addEventListener('change', function () {
|
||||||
term.setOption('bellStyle', optionElements.bellStyle.value);
|
term.setOption('bellStyle', optionElements.bellStyle.value);
|
||||||
});
|
});
|
||||||
|
optionElements.macOptionIsMeta.addEventListener('change', function () {
|
||||||
|
term.setOption('macOptionIsMeta', optionElements.macOptionIsMeta.checked);
|
||||||
|
});
|
||||||
optionElements.scrollback.addEventListener('change', function () {
|
optionElements.scrollback.addEventListener('change', function () {
|
||||||
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
|
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
|
||||||
});
|
});
|
||||||
@@ -87,6 +91,7 @@ function createTerminal() {
|
|||||||
terminalContainer.removeChild(terminalContainer.children[0]);
|
terminalContainer.removeChild(terminalContainer.children[0]);
|
||||||
}
|
}
|
||||||
term = new Terminal({
|
term = new Terminal({
|
||||||
|
macOptionIsMeta: optionElements.macOptionIsMeta.enabled,
|
||||||
cursorBlink: optionElements.cursorBlink.checked,
|
cursorBlink: optionElements.cursorBlink.checked,
|
||||||
scrollback: parseInt(optionElements.scrollback.value, 10),
|
scrollback: parseInt(optionElements.scrollback.value, 10),
|
||||||
tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
|
tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10)
|
||||||
|
|||||||
@@ -144,6 +144,9 @@ namespace methods_core {
|
|||||||
const r20: string = t.getOption('bellStyle');
|
const r20: string = t.getOption('bellStyle');
|
||||||
const r21: boolean = t.getOption('enableBold');
|
const r21: boolean = t.getOption('enableBold');
|
||||||
const r22: number = t.getOption('letterSpacing');
|
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();
|
const t: Terminal = new Terminal();
|
||||||
@@ -156,7 +159,10 @@ namespace methods_core {
|
|||||||
t.setOption('cursorBlink', true);
|
t.setOption('cursorBlink', true);
|
||||||
t.setOption('debug', true);
|
t.setOption('debug', true);
|
||||||
t.setOption('disableStdin', 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('popOnBell', true);
|
||||||
t.setOption('screenKeys', true);
|
t.setOption('screenKeys', true);
|
||||||
t.setOption('useFlowControl', true);
|
t.setOption('useFlowControl', true);
|
||||||
@@ -177,6 +183,7 @@ namespace methods_core {
|
|||||||
t.setOption('lineHeight', 1);
|
t.setOption('lineHeight', 1);
|
||||||
t.setOption('fontFamily', 'foo');
|
t.setOption('fontFamily', 'foo');
|
||||||
t.setOption('theme', {background: '#ff0000'});
|
t.setOption('theme', {background: '#ff0000'});
|
||||||
|
t.setOption('macOptionIsMeta', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace scrolling {
|
namespace scrolling {
|
||||||
|
|||||||
+38
-46
@@ -18,11 +18,13 @@ const ts = require('gulp-typescript');
|
|||||||
const util = require('gulp-util');
|
const util = require('gulp-util');
|
||||||
const webpack = require('webpack-stream');
|
const webpack = require('webpack-stream');
|
||||||
|
|
||||||
let buildDir = process.env.BUILD_DIR || 'build';
|
const buildDir = process.env.BUILD_DIR || 'build';
|
||||||
let tsProject = ts.createProject('tsconfig.json');
|
const tsProject = ts.createProject('tsconfig.json');
|
||||||
let srcDir = tsProject.config.compilerOptions.rootDir;
|
const srcDir = tsProject.config.compilerOptions.rootDir;
|
||||||
let outDir = tsProject.config.compilerOptions.outDir;
|
let outDir = tsProject.config.compilerOptions.outDir;
|
||||||
|
|
||||||
|
const addons = ['attach', 'fit', 'fullscreen', 'search', 'terminado', 'winptyCompat', 'zmodem'];
|
||||||
|
|
||||||
// Under some environments like TravisCI, this comes out at absolute which can
|
// Under some environments like TravisCI, this comes out at absolute which can
|
||||||
// break the build. This ensures that the outDir is absolute.
|
// break the build. This ensures that the outDir is absolute.
|
||||||
if (path.normalize(outDir).indexOf(__dirname) !== 0) {
|
if (path.normalize(outDir).indexOf(__dirname) !== 0) {
|
||||||
@@ -45,15 +47,19 @@ gulp.task('tsc', function () {
|
|||||||
tsResult.dts.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(outDir))
|
tsResult.dts.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(outDir))
|
||||||
);
|
);
|
||||||
|
|
||||||
let addons = ['attach', 'fit', 'fullscreen', 'search', 'terminado', 'winptyCompat', 'zmodem'];
|
|
||||||
let addonStreams = addons.map(function(addon) {
|
let addonStreams = addons.map(function(addon) {
|
||||||
fs.emptyDirSync(`${outDir}/addons/${addon}`);
|
fs.emptyDirSync(`${outDir}/addons/${addon}`);
|
||||||
|
|
||||||
let tsProjectAddon = ts.createProject(`./src/addons/${addon}/tsconfig.json`);
|
let tsProjectAddon = ts.createProject(`./src/addons/${addon}/tsconfig.json`);
|
||||||
let tsResultAddon = tsProjectAddon.src().pipe(sourcemaps.init()).pipe(tsProjectAddon());
|
let tsResultAddon = tsProjectAddon.src().pipe(sourcemaps.init()).pipe(tsProjectAddon());
|
||||||
let tscAddon = tsResultAddon.js
|
let tscAddon = merge(
|
||||||
.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''}))
|
tsResultAddon.js
|
||||||
.pipe(gulp.dest(`${outDir}/addons/${addon}`));
|
.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''}))
|
||||||
|
.pipe(gulp.dest(`${outDir}/addons/${addon}`)),
|
||||||
|
tsResultAddon.dts
|
||||||
|
.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''}))
|
||||||
|
.pipe(gulp.dest(`${outDir}/addons/${addon}`))
|
||||||
|
)
|
||||||
|
|
||||||
return tscAddon;
|
return tscAddon;
|
||||||
});
|
});
|
||||||
@@ -103,45 +109,29 @@ gulp.task('browserify', ['tsc'], function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('browserify-addons', ['tsc'], function() {
|
gulp.task('browserify-addons', ['tsc'], function() {
|
||||||
let searchOptions = {
|
const bundles = addons.map((addon) => {
|
||||||
basedir: `${buildDir}/addons/search`,
|
const addonOptions = {
|
||||||
debug: true,
|
basedir: `${buildDir}/addons/${addon}`,
|
||||||
entries: [`${outDir}/addons/search/search.js`],
|
debug: true,
|
||||||
cache: {},
|
entries: [`${outDir}/addons/${addon}/${addon}.js`],
|
||||||
packageCache: {}
|
standalone: addon,
|
||||||
};
|
cache: {},
|
||||||
let searchBundle = browserify(searchOptions)
|
packageCache: {}
|
||||||
.external(path.join(outDir, 'Terminal.js'))
|
};
|
||||||
.bundle()
|
|
||||||
.pipe(source('./addons/search/search.js'))
|
|
||||||
.pipe(buffer())
|
|
||||||
.pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''}))
|
|
||||||
.pipe(sourcemaps.write('./'))
|
|
||||||
.pipe(gulp.dest(buildDir));
|
|
||||||
|
|
||||||
let winptyCompatOptions = {
|
const addonBundle = browserify(addonOptions)
|
||||||
basedir: `${buildDir}/addons/winptyCompat`,
|
.external(path.join(outDir, 'Terminal.js'))
|
||||||
debug: true,
|
.bundle()
|
||||||
entries: [`${outDir}/addons/winptyCompat/winptyCompat.js`],
|
.pipe(source(`./addons/${addon}/${addon}.js`))
|
||||||
cache: {},
|
.pipe(buffer())
|
||||||
packageCache: {}
|
.pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''}))
|
||||||
};
|
.pipe(sourcemaps.write('./'))
|
||||||
let winptyCompatBundle = browserify(winptyCompatOptions)
|
.pipe(gulp.dest(buildDir));
|
||||||
.external(path.join(outDir, 'Terminal.js'))
|
|
||||||
.bundle()
|
|
||||||
.pipe(source('./addons/winptyCompat/winptyCompat.js'))
|
|
||||||
.pipe(buffer())
|
|
||||||
.pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''}))
|
|
||||||
.pipe(sourcemaps.write('./'))
|
|
||||||
.pipe(gulp.dest(buildDir));
|
|
||||||
|
|
||||||
// Copy all add-ons from outDir to buildDir
|
return addonBundle;
|
||||||
let copyAddons = gulp.src([
|
});
|
||||||
// Copy JS addons
|
|
||||||
`${outDir}/addons/**/*`
|
|
||||||
]).pipe(gulp.dest(`${buildDir}/addons`));
|
|
||||||
|
|
||||||
return merge(searchBundle, winptyCompatBundle, copyAddons);
|
return merge(...bundles);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('instrument-test', function () {
|
gulp.task('instrument-test', function () {
|
||||||
@@ -189,9 +179,11 @@ gulp.task('sorcery', ['browserify'], function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sorcery-addons', ['browserify-addons'], function () {
|
gulp.task('sorcery-addons', ['browserify-addons'], function () {
|
||||||
var chain = sorcery.loadSync(`${buildDir}/addons/search/search.js`);
|
addons.forEach((addon) => {
|
||||||
chain.apply();
|
const chain = sorcery.loadSync(`${buildDir}/addons/${addon}/${addon}.js`);
|
||||||
chain.writeSync();
|
chain.apply();
|
||||||
|
chain.writeSync();
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('webpack', ['build'], function() {
|
gulp.task('webpack', ['build'], function() {
|
||||||
|
|||||||
Generated
+251
-759
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -66,7 +66,7 @@
|
|||||||
"node-pty": "^0.7.2",
|
"node-pty": "^0.7.2",
|
||||||
"nodemon": "1.10.2",
|
"nodemon": "1.10.2",
|
||||||
"sorcery": "^0.10.0",
|
"sorcery": "^0.10.0",
|
||||||
"tslint": "^4.0.2",
|
"tslint": "^5.9.1",
|
||||||
"typescript": "~2.4.0",
|
"typescript": "~2.4.0",
|
||||||
"vinyl-buffer": "^1.0.0",
|
"vinyl-buffer": "^1.0.0",
|
||||||
"vinyl-source-stream": "^1.1.0",
|
"vinyl-source-stream": "^1.1.0",
|
||||||
|
|||||||
@@ -121,11 +121,6 @@ export class Buffer implements IBuffer {
|
|||||||
if (this._terminal.cols < newCols) {
|
if (this._terminal.cols < newCols) {
|
||||||
const ch: CharData = [this._terminal.defAttr, ' ', 1, 32]; // does xterm use the default attr?
|
const ch: CharData = [this._terminal.defAttr, ' ', 1, 32]; // does xterm use the default attr?
|
||||||
for (let i = 0; i < this._lines.length; i++) {
|
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) {
|
while (this._lines.get(i).length < newCols) {
|
||||||
this._lines.get(i).push(ch);
|
this._lines.get(i).push(ch);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-3
@@ -61,24 +61,35 @@ export class BufferSet extends EventEmitter implements IBufferSet {
|
|||||||
* Sets the normal Buffer of the BufferSet as its currently active Buffer
|
* Sets the normal Buffer of the BufferSet as its currently active Buffer
|
||||||
*/
|
*/
|
||||||
public activateNormalBuffer(): void {
|
public activateNormalBuffer(): void {
|
||||||
|
if (this._activeBuffer === this._normal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// The alt buffer should always be cleared when we switch to the normal
|
// 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
|
// buffer. This frees up memory since the alt buffer should always be new
|
||||||
// when activated.
|
// when activated.
|
||||||
this._alt.clear();
|
this._alt.clear();
|
||||||
|
|
||||||
this._activeBuffer = this._normal;
|
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
|
* Sets the alt Buffer of the BufferSet as its currently active Buffer
|
||||||
*/
|
*/
|
||||||
public activateAltBuffer(): void {
|
public activateAltBuffer(): void {
|
||||||
|
if (this._activeBuffer === this._alt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Since the alt buffer is always cleared when the normal buffer is
|
// Since the alt buffer is always cleared when the normal buffer is
|
||||||
// activated, we want to fill it when switching to it.
|
// activated, we want to fill it when switching to it.
|
||||||
this._alt.fillViewportRows();
|
this._alt.fillViewportRows();
|
||||||
this._activeBuffer = this._alt;
|
this._activeBuffer = this._alt;
|
||||||
this.emit('activate', this._alt);
|
this.emit('activate', {
|
||||||
|
activeBuffer: this._alt,
|
||||||
|
inactiveBuffer: this._normal
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
-3
@@ -3,19 +3,19 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Charset } from './Types';
|
import { ICharset } from './Interfaces';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The character sets supported by the terminal. These enable several languages
|
* The character sets supported by the terminal. These enable several languages
|
||||||
* to be represented within the terminal with only 8-bit encoding. See ISO 2022
|
* to be represented within the terminal with only 8-bit encoding. See ISO 2022
|
||||||
* for a discussion on character sets. Only VT100 character sets are supported.
|
* for a discussion on character sets. Only VT100 character sets are supported.
|
||||||
*/
|
*/
|
||||||
export const CHARSETS: { [key: string]: Charset } = {};
|
export const CHARSETS: { [key: string]: ICharset } = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default character set, US.
|
* The default character set, US.
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_CHARSET: Charset = CHARSETS['B'];
|
export const DEFAULT_CHARSET: ICharset = CHARSETS['B'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEC Special Character and Line Drawing Set.
|
* DEC Special Character and Line Drawing Set.
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ export class CompositionHelper {
|
|||||||
if (!dontRecurse) {
|
if (!dontRecurse) {
|
||||||
setTimeout(() => this.updateCompositionElements(true), 0);
|
setTimeout(() => this.updateCompositionElements(true), 0);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the textarea's position so that the cursor does not blink on IE.
|
* Clears the textarea's position so that the cursor does not blink on IE.
|
||||||
@@ -226,5 +226,5 @@ export class CompositionHelper {
|
|||||||
private clearTextareaPosition(): void {
|
private clearTextareaPosition(): void {
|
||||||
this.textarea.style.left = '';
|
this.textarea.style.left = '';
|
||||||
this.textarea.style.top = '';
|
this.textarea.style.top = '';
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,4 +76,4 @@ export namespace C0 {
|
|||||||
export const SP = '\x20';
|
export const SP = '\x20';
|
||||||
/** Delete (Caret = ^?) */
|
/** Delete (Caret = ^?) */
|
||||||
export const DEL = '\x7f';
|
export const DEL = '\x7f';
|
||||||
};
|
}
|
||||||
|
|||||||
+7
-9
@@ -26,7 +26,7 @@ export class InputHandler implements IInputHandler {
|
|||||||
if (char >= ' ') {
|
if (char >= ' ') {
|
||||||
// calculate print space
|
// calculate print space
|
||||||
// expensive call, therefore we save width in line buffer
|
// expensive call, therefore we save width in line buffer
|
||||||
const ch_width = wcwidth(code);
|
const chWidth = wcwidth(code);
|
||||||
|
|
||||||
if (this._terminal.charset && this._terminal.charset[char]) {
|
if (this._terminal.charset && this._terminal.charset[char]) {
|
||||||
char = this._terminal.charset[char];
|
char = this._terminal.charset[char];
|
||||||
@@ -36,7 +36,7 @@ export class InputHandler implements IInputHandler {
|
|||||||
|
|
||||||
// insert combining char in last cell
|
// insert combining char in last cell
|
||||||
// FIXME: needs handling after cursor jumps
|
// FIXME: needs handling after cursor jumps
|
||||||
if (!ch_width && this._terminal.buffer.x) {
|
if (!chWidth && this._terminal.buffer.x) {
|
||||||
// dont overflow left
|
// dont overflow left
|
||||||
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) {
|
if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) {
|
||||||
if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) {
|
if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) {
|
||||||
@@ -56,7 +56,7 @@ export class InputHandler implements IInputHandler {
|
|||||||
|
|
||||||
// goto next line if ch would overflow
|
// goto next line if ch would overflow
|
||||||
// TODO: needs a global min terminal width of 2
|
// TODO: needs a global min terminal width of 2
|
||||||
if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) {
|
if (this._terminal.buffer.x + chWidth - 1 >= this._terminal.cols) {
|
||||||
// autowrap - DECAWM
|
// autowrap - DECAWM
|
||||||
if (this._terminal.wraparoundMode) {
|
if (this._terminal.wraparoundMode) {
|
||||||
this._terminal.buffer.x = 0;
|
this._terminal.buffer.x = 0;
|
||||||
@@ -70,7 +70,7 @@ export class InputHandler implements IInputHandler {
|
|||||||
(<any>this._terminal.buffer.lines.get(this._terminal.buffer.y)).isWrapped = true;
|
(<any>this._terminal.buffer.lines.get(this._terminal.buffer.y)).isWrapped = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ch_width === 2) // FIXME: check for xterm behavior
|
if (chWidth === 2) // FIXME: check for xterm behavior
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ export class InputHandler implements IInputHandler {
|
|||||||
// insert mode: move characters to right
|
// insert mode: move characters to right
|
||||||
if (this._terminal.insertMode) {
|
if (this._terminal.insertMode) {
|
||||||
// do this twice for a fullwidth char
|
// do this twice for a fullwidth char
|
||||||
for (let moves = 0; moves < ch_width; ++moves) {
|
for (let moves = 0; moves < chWidth; ++moves) {
|
||||||
// remove last cell, if it's width is 0
|
// remove last cell, if it's width is 0
|
||||||
// we have to adjust the second last cell as well
|
// we have to adjust the second last cell as well
|
||||||
const removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop();
|
const removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop();
|
||||||
@@ -94,12 +94,12 @@ export class InputHandler implements IInputHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)];
|
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, chWidth, char.charCodeAt(0)];
|
||||||
this._terminal.buffer.x++;
|
this._terminal.buffer.x++;
|
||||||
this._terminal.updateRange(this._terminal.buffer.y);
|
this._terminal.updateRange(this._terminal.buffer.y);
|
||||||
|
|
||||||
// fullwidth char - set next cell width to zero and advance cursor
|
// fullwidth char - set next cell width to zero and advance cursor
|
||||||
if (ch_width === 2) {
|
if (chWidth === 2) {
|
||||||
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined];
|
this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined];
|
||||||
this._terminal.buffer.x++;
|
this._terminal.buffer.x++;
|
||||||
}
|
}
|
||||||
@@ -928,7 +928,6 @@ export class InputHandler implements IInputHandler {
|
|||||||
case 47: // alt screen buffer
|
case 47: // alt screen buffer
|
||||||
case 1047: // alt screen buffer
|
case 1047: // alt screen buffer
|
||||||
this._terminal.buffers.activateAltBuffer();
|
this._terminal.buffers.activateAltBuffer();
|
||||||
this._terminal.selectionManager.setBuffer(this._terminal.buffer);
|
|
||||||
this._terminal.viewport.syncScrollArea();
|
this._terminal.viewport.syncScrollArea();
|
||||||
this._terminal.showCursor();
|
this._terminal.showCursor();
|
||||||
break;
|
break;
|
||||||
@@ -1100,7 +1099,6 @@ export class InputHandler implements IInputHandler {
|
|||||||
// if (params[0] === 1049) {
|
// if (params[0] === 1049) {
|
||||||
// this.restoreCursor(params);
|
// this.restoreCursor(params);
|
||||||
// }
|
// }
|
||||||
this._terminal.selectionManager.setBuffer(this._terminal.buffer);
|
|
||||||
this._terminal.refresh(0, this._terminal.rows - 1);
|
this._terminal.refresh(0, this._terminal.rows - 1);
|
||||||
this._terminal.viewport.syncScrollArea();
|
this._terminal.viewport.syncScrollArea();
|
||||||
this._terminal.showCursor();
|
this._terminal.showCursor();
|
||||||
|
|||||||
+31
-9
@@ -3,8 +3,8 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ILinkMatcherOptions } from './Interfaces';
|
import { ICharset, ILinkMatcherOptions } from './Interfaces';
|
||||||
import { LinkMatcherHandler, LinkMatcherValidationCallback, Charset, LineData } from './Types';
|
import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData, FontWeight } from './Types';
|
||||||
import { IColorSet, IRenderer } from './renderer/Interfaces';
|
import { IColorSet, IRenderer } from './renderer/Interfaces';
|
||||||
import { IMouseZoneManager } from './input/Interfaces';
|
import { IMouseZoneManager } from './input/Interfaces';
|
||||||
|
|
||||||
@@ -74,10 +74,10 @@ export interface IInputHandlingTerminal extends IEventEmitter {
|
|||||||
options: ITerminalOptions;
|
options: ITerminalOptions;
|
||||||
cols: number;
|
cols: number;
|
||||||
rows: number;
|
rows: number;
|
||||||
charset: Charset;
|
charset: ICharset;
|
||||||
gcharset: number;
|
gcharset: number;
|
||||||
glevel: number;
|
glevel: number;
|
||||||
charsets: Charset[];
|
charsets: ICharset[];
|
||||||
applicationKeypad: boolean;
|
applicationKeypad: boolean;
|
||||||
applicationCursor: boolean;
|
applicationCursor: boolean;
|
||||||
originMode: boolean;
|
originMode: boolean;
|
||||||
@@ -116,7 +116,7 @@ export interface IInputHandlingTerminal extends IEventEmitter {
|
|||||||
blankLine(cur?: boolean, isWrapped?: boolean): LineData;
|
blankLine(cur?: boolean, isWrapped?: boolean): LineData;
|
||||||
is(term: string): boolean;
|
is(term: string): boolean;
|
||||||
send(data: string): void;
|
send(data: string): void;
|
||||||
setgCharset(g: number, charset: Charset): void;
|
setgCharset(g: number, charset: ICharset): void;
|
||||||
resize(x: number, y: number): void;
|
resize(x: number, y: number): void;
|
||||||
log(text: string, data?: any): void;
|
log(text: string, data?: any): void;
|
||||||
reset(): void;
|
reset(): void;
|
||||||
@@ -137,12 +137,14 @@ export interface ITerminalOptions {
|
|||||||
cursorStyle?: string;
|
cursorStyle?: string;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
disableStdin?: boolean;
|
disableStdin?: boolean;
|
||||||
enableBold?: boolean;
|
|
||||||
fontSize?: number;
|
fontSize?: number;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
|
fontWeight?: FontWeight;
|
||||||
|
fontWeightBold?: FontWeight;
|
||||||
handler?: (data: string) => void;
|
handler?: (data: string) => void;
|
||||||
letterSpacing?: number;
|
letterSpacing?: number;
|
||||||
lineHeight?: number;
|
lineHeight?: number;
|
||||||
|
macOptionIsMeta?: boolean;
|
||||||
rows?: number;
|
rows?: number;
|
||||||
screenKeys?: boolean;
|
screenKeys?: boolean;
|
||||||
scrollback?: number;
|
scrollback?: number;
|
||||||
@@ -169,7 +171,7 @@ export interface IBuffer {
|
|||||||
prevStop(x?: number): number;
|
prevStop(x?: number): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBufferSet {
|
export interface IBufferSet extends IEventEmitter {
|
||||||
alt: IBuffer;
|
alt: IBuffer;
|
||||||
normal: IBuffer;
|
normal: IBuffer;
|
||||||
active: IBuffer;
|
active: IBuffer;
|
||||||
@@ -198,7 +200,6 @@ export interface ISelectionManager {
|
|||||||
|
|
||||||
disable(): void;
|
disable(): void;
|
||||||
enable(): void;
|
enable(): void;
|
||||||
setBuffer(buffer: IBuffer): void;
|
|
||||||
setSelection(row: number, col: number, length: number): void;
|
setSelection(row: number, col: number, length: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ export interface IEventEmitter {
|
|||||||
export interface IListenerType {
|
export interface IListenerType {
|
||||||
(data?: any): void;
|
(data?: any): void;
|
||||||
listener?: (data?: any) => void;
|
listener?: (data?: any) => void;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface ILinkMatcherOptions {
|
export interface ILinkMatcherOptions {
|
||||||
/**
|
/**
|
||||||
@@ -352,3 +353,24 @@ export interface ITheme {
|
|||||||
brightCyan?: string;
|
brightCyan?: string;
|
||||||
brightWhite?: string;
|
brightWhite?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ILinkMatcher {
|
||||||
|
id: number;
|
||||||
|
regex: RegExp;
|
||||||
|
handler: LinkMatcherHandler;
|
||||||
|
hoverTooltipCallback?: LinkMatcherHandler;
|
||||||
|
hoverLeaveCallback?: () => void;
|
||||||
|
matchIndex?: number;
|
||||||
|
validationCallback?: LinkMatcherValidationCallback;
|
||||||
|
priority?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICharset {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILinkHoverEvent {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
length: number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import { ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor } from './Interfaces';
|
import { ITerminal, ILinkifier, ILinkMatcher, IBuffer, IBufferAccessor, IElementAccessor } from './Interfaces';
|
||||||
import { Linkifier } from './Linkifier';
|
import { Linkifier } from './Linkifier';
|
||||||
import { LinkMatcher, LineData } from './Types';
|
import { LineData } from './Types';
|
||||||
import { IMouseZoneManager, IMouseZone } from './input/Interfaces';
|
import { IMouseZoneManager, IMouseZone } from './input/Interfaces';
|
||||||
import { MockBuffer } from './utils/TestUtils.test';
|
import { MockBuffer } from './utils/TestUtils.test';
|
||||||
import { CircularList } from './utils/CircularList';
|
import { CircularList } from './utils/CircularList';
|
||||||
@@ -17,7 +17,7 @@ class TestLinkifier extends Linkifier {
|
|||||||
Linkifier.TIME_BEFORE_LINKIFY = 0;
|
Linkifier.TIME_BEFORE_LINKIFY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get linkMatchers(): LinkMatcher[] { return this._linkMatchers; }
|
public get linkMatchers(): ILinkMatcher[] { return this._linkMatchers; }
|
||||||
public linkifyRows(): void { super.linkifyRows(0, this._terminal.buffer.lines.length - 1); }
|
public linkifyRows(): void { super.linkifyRows(0, this._terminal.buffer.lines.length - 1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -3,8 +3,8 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces';
|
import { ILinkHoverEvent, ILinkMatcher, ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces';
|
||||||
import { LinkMatcher, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEvent, LinkHoverEventTypes } from './Types';
|
import { LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEventTypes } from './Types';
|
||||||
import { IMouseZoneManager } from './input/Interfaces';
|
import { IMouseZoneManager } from './input/Interfaces';
|
||||||
import { MouseZone } from './input/MouseZoneManager';
|
import { MouseZone } from './input/MouseZoneManager';
|
||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
@@ -44,7 +44,7 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
*/
|
*/
|
||||||
protected static TIME_BEFORE_LINKIFY = 200;
|
protected static TIME_BEFORE_LINKIFY = 200;
|
||||||
|
|
||||||
protected _linkMatchers: LinkMatcher[] = [];
|
protected _linkMatchers: ILinkMatcher[] = [];
|
||||||
|
|
||||||
private _mouseZoneManager: IMouseZoneManager;
|
private _mouseZoneManager: IMouseZoneManager;
|
||||||
private _rowsTimeoutId: number;
|
private _rowsTimeoutId: number;
|
||||||
@@ -82,12 +82,12 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Increase range to linkify
|
// Increase range to linkify
|
||||||
if (!this._rowsToLinkify.start) {
|
if (this._rowsToLinkify.start === null) {
|
||||||
this._rowsToLinkify.start = start;
|
this._rowsToLinkify.start = start;
|
||||||
this._rowsToLinkify.end = end;
|
this._rowsToLinkify.end = end;
|
||||||
} else {
|
} else {
|
||||||
this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start;
|
this._rowsToLinkify.start = Math.min(this._rowsToLinkify.start, start);
|
||||||
this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end;
|
this._rowsToLinkify.end = Math.max(this._rowsToLinkify.end, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear out any existing links on this row range
|
// Clear out any existing links on this row range
|
||||||
@@ -143,7 +143,7 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) {
|
if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) {
|
||||||
throw new Error('handler must be defined');
|
throw new Error('handler must be defined');
|
||||||
}
|
}
|
||||||
const matcher: LinkMatcher = {
|
const matcher: ILinkMatcher = {
|
||||||
id: this._nextLinkMatcherId++,
|
id: this._nextLinkMatcherId++,
|
||||||
regex,
|
regex,
|
||||||
handler,
|
handler,
|
||||||
@@ -163,7 +163,7 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
* considered after older link matchers.
|
* considered after older link matchers.
|
||||||
* @param matcher The link matcher to be added.
|
* @param matcher The link matcher to be added.
|
||||||
*/
|
*/
|
||||||
private _addLinkMatcherToList(matcher: LinkMatcher): void {
|
private _addLinkMatcherToList(matcher: ILinkMatcher): void {
|
||||||
if (this._linkMatchers.length === 0) {
|
if (this._linkMatchers.length === 0) {
|
||||||
this._linkMatchers.push(matcher);
|
this._linkMatchers.push(matcher);
|
||||||
return;
|
return;
|
||||||
@@ -219,7 +219,7 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
* @param offset The how much of the row has already been linkified.
|
* @param offset The how much of the row has already been linkified.
|
||||||
* @return The link element(s) that were added.
|
* @return The link element(s) that were added.
|
||||||
*/
|
*/
|
||||||
private _doLinkifyRow(rowIndex: number, text: string, matcher: LinkMatcher, offset: number = 0): void {
|
private _doLinkifyRow(rowIndex: number, text: string, matcher: ILinkMatcher, offset: number = 0): void {
|
||||||
// Iterate over nodes as we want to consider text nodes
|
// Iterate over nodes as we want to consider text nodes
|
||||||
let result = [];
|
let result = [];
|
||||||
const isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID;
|
const isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID;
|
||||||
@@ -264,7 +264,7 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
* @param uri The URI of the link.
|
* @param uri The URI of the link.
|
||||||
* @param matcher The link matcher for the link.
|
* @param matcher The link matcher for the link.
|
||||||
*/
|
*/
|
||||||
private _addLink(x: number, y: number, uri: string, matcher: LinkMatcher): void {
|
private _addLink(x: number, y: number, uri: string, matcher: ILinkMatcher): void {
|
||||||
this._mouseZoneManager.add(new MouseZone(
|
this._mouseZoneManager.add(new MouseZone(
|
||||||
x + 1,
|
x + 1,
|
||||||
x + 1 + uri.length,
|
x + 1 + uri.length,
|
||||||
@@ -276,17 +276,17 @@ export class Linkifier extends EventEmitter implements ILinkifier {
|
|||||||
window.open(uri, '_blank');
|
window.open(uri, '_blank');
|
||||||
},
|
},
|
||||||
e => {
|
e => {
|
||||||
this.emit(LinkHoverEventTypes.HOVER, <LinkHoverEvent>{ x, y, length: uri.length});
|
this.emit(LinkHoverEventTypes.HOVER, <ILinkHoverEvent>{ x, y, length: uri.length});
|
||||||
this._terminal.element.style.cursor = 'pointer';
|
this._terminal.element.style.cursor = 'pointer';
|
||||||
},
|
},
|
||||||
e => {
|
e => {
|
||||||
this.emit(LinkHoverEventTypes.TOOLTIP, <LinkHoverEvent>{ x, y, length: uri.length});
|
this.emit(LinkHoverEventTypes.TOOLTIP, <ILinkHoverEvent>{ x, y, length: uri.length});
|
||||||
if (matcher.hoverTooltipCallback) {
|
if (matcher.hoverTooltipCallback) {
|
||||||
matcher.hoverTooltipCallback(e, uri);
|
matcher.hoverTooltipCallback(e, uri);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.emit(LinkHoverEventTypes.LEAVE, <LinkHoverEvent>{ x, y, length: uri.length});
|
this.emit(LinkHoverEventTypes.LEAVE, <ILinkHoverEvent>{ x, y, length: uri.length});
|
||||||
this._terminal.element.style.cursor = '';
|
this._terminal.element.style.cursor = '';
|
||||||
if (matcher.hoverLeaveCallback) {
|
if (matcher.hoverLeaveCallback) {
|
||||||
matcher.hoverLeaveCallback();
|
matcher.hoverLeaveCallback();
|
||||||
|
|||||||
@@ -21,10 +21,9 @@ class TestMockTerminal extends MockTerminal {
|
|||||||
class TestSelectionManager extends SelectionManager {
|
class TestSelectionManager extends SelectionManager {
|
||||||
constructor(
|
constructor(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
buffer: IBuffer,
|
|
||||||
charMeasure: CharMeasure
|
charMeasure: CharMeasure
|
||||||
) {
|
) {
|
||||||
super(terminal, buffer, charMeasure);
|
super(terminal, charMeasure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get model(): SelectionModel { return this._model; }
|
public get model(): SelectionModel { return this._model; }
|
||||||
@@ -59,7 +58,7 @@ describe('SelectionManager', () => {
|
|||||||
terminal.buffers = new BufferSet(terminal);
|
terminal.buffers = new BufferSet(terminal);
|
||||||
terminal.buffer = terminal.buffers.active;
|
terminal.buffer = terminal.buffers.active;
|
||||||
buffer = terminal.buffer;
|
buffer = terminal.buffer;
|
||||||
selectionManager = new TestSelectionManager(terminal, buffer, null);
|
selectionManager = new TestSelectionManager(terminal, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
function stringToRow(text: string): LineData {
|
function stringToRow(text: string): LineData {
|
||||||
|
|||||||
+23
-17
@@ -8,7 +8,7 @@ import * as Browser from './utils/Browser';
|
|||||||
import { CharMeasure } from './utils/CharMeasure';
|
import { CharMeasure } from './utils/CharMeasure';
|
||||||
import { CircularList } from './utils/CircularList';
|
import { CircularList } from './utils/CircularList';
|
||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
import { ITerminal, ICircularList, ISelectionManager, IBuffer } from './Interfaces';
|
import { ITerminal, ICircularList, ISelectionManager, IBuffer, IListenerType } from './Interfaces';
|
||||||
import { SelectionModel } from './SelectionModel';
|
import { SelectionModel } from './SelectionModel';
|
||||||
import { LineData, CharData } from './Types';
|
import { LineData, CharData } from './Types';
|
||||||
import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer';
|
import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer';
|
||||||
@@ -95,10 +95,10 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
|||||||
|
|
||||||
private _mouseMoveListener: EventListener;
|
private _mouseMoveListener: EventListener;
|
||||||
private _mouseUpListener: EventListener;
|
private _mouseUpListener: EventListener;
|
||||||
|
private _trimListener: IListenerType;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _terminal: ITerminal,
|
private _terminal: ITerminal,
|
||||||
private _buffer: IBuffer,
|
|
||||||
private _charMeasure: CharMeasure
|
private _charMeasure: CharMeasure
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -109,18 +109,24 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
|||||||
this._activeSelectionMode = SelectionMode.NORMAL;
|
this._activeSelectionMode = SelectionMode.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get _buffer(): IBuffer {
|
||||||
|
return this._terminal.buffers.active;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes listener variables.
|
* Initializes listener variables.
|
||||||
*/
|
*/
|
||||||
private _initListeners(): void {
|
private _initListeners(): void {
|
||||||
this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
|
this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
|
||||||
this._mouseUpListener = event => this._onMouseUp(<MouseEvent>event);
|
this._mouseUpListener = event => this._onMouseUp(<MouseEvent>event);
|
||||||
|
this._trimListener = (amount: number) => this._onTrim(amount);
|
||||||
|
|
||||||
// Only adjust the selection on trim, shiftElements is rarely used (only in
|
this.initBuffersListeners();
|
||||||
// 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.
|
public initBuffersListeners(): void {
|
||||||
this._buffer.lines.on('trim', (amount: number) => this._onTrim(amount));
|
this._terminal.buffer.lines.on('trim', this._trimListener);
|
||||||
|
this._terminal.buffers.on('activate', e => this._onBufferActivate(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,16 +145,6 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
|||||||
this._enabled = true;
|
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 selectionStart(): [number, number] { return this._model.finalSelectionStart; }
|
||||||
public get selectionEnd(): [number, number] { return this._model.finalSelectionEnd; }
|
public get selectionEnd(): [number, number] { return this._model.finalSelectionEnd; }
|
||||||
|
|
||||||
@@ -547,6 +543,16 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
|
|||||||
this._terminal.emit('selection');
|
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
|
* Converts a viewport column to the character index on the buffer line, the
|
||||||
* latter takes into account wide characters.
|
* latter takes into account wide characters.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import { ITerminal } from './Interfaces';
|
import { ITerminal } from './Interfaces';
|
||||||
import { SelectionModel } from './SelectionModel';
|
import { SelectionModel } from './SelectionModel';
|
||||||
import {BufferSet} from './BufferSet';
|
import { BufferSet } from './BufferSet';
|
||||||
import { MockTerminal } from './utils/TestUtils.test';
|
import { MockTerminal } from './utils/TestUtils.test';
|
||||||
|
|
||||||
class TestSelectionModel extends SelectionModel {
|
class TestSelectionModel extends SelectionModel {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user