mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #2288 from jerch/cleanup_sequences_files
fix edge cases in inputhandler methods
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
from glob import glob
|
||||
import os
|
||||
import sys
|
||||
import termios
|
||||
import atexit
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def enable_echo(fd, enabled):
|
||||
(iflag, oflag, cflag, lflag, ispeed, ospeed, cc) = termios.tcgetattr(fd)
|
||||
if enabled:
|
||||
lflag |= termios.ECHO
|
||||
else:
|
||||
lflag &= ~termios.ECHO
|
||||
new_attr = [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
|
||||
termios.tcsetattr(fd, termios.TCSANOW, new_attr)
|
||||
|
||||
atexit.register(enable_echo, sys.stdin.fileno(), True)
|
||||
|
||||
output = []
|
||||
|
||||
|
||||
def log(append=False, *s):
|
||||
if append:
|
||||
output[-1] += ' ' + ' '.join(str(part) for part in s)
|
||||
else:
|
||||
output.append(' '.join(str(part) for part in s))
|
||||
|
||||
|
||||
def reset_terminal():
|
||||
sys.stdout.write('\x1bc\x1b[H')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def test():
|
||||
count = 0
|
||||
passed = 0
|
||||
for i, testfile in enumerate(sorted(glob(os.path.join(BASE_DIR, '*.in')))):
|
||||
count += 1
|
||||
log(False, os.path.basename(testfile))
|
||||
reset_terminal()
|
||||
with open(testfile) as test:
|
||||
sys.stdout.write('\x1b]0;%s\x07' % os.path.basename(testfile))
|
||||
sys.stdout.write(test.read()+'\x1bt')
|
||||
sys.stdout.flush()
|
||||
with open(os.path.join(os.path.dirname(testfile),
|
||||
os.path.basename(testfile).split('.')[0]+'.text')) as expected:
|
||||
terminal_output = sys.stdin.read()
|
||||
if not terminal_output:
|
||||
# we are in xterm
|
||||
continue
|
||||
if terminal_output != expected.read():
|
||||
log(True, '\x1b[31merror\x1b[0m')
|
||||
with open(os.path.join(os.path.dirname(testfile), 'output',
|
||||
os.path.basename(testfile)), 'w') as t_out:
|
||||
t_out.write(terminal_output)
|
||||
else:
|
||||
passed += 1
|
||||
log(True, '\x1b[32mpass\x1b[0m')
|
||||
return count, passed
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
enable_echo(sys.stdin.fileno(), False)
|
||||
count, passed = test()
|
||||
enable_echo(sys.stdin.fileno(), True)
|
||||
reset_terminal()
|
||||
for i in range(len(output)/2+1):
|
||||
if not (i+1) % 25:
|
||||
sys.stdin.read()
|
||||
print ''.join(i.ljust(40) for i in output[i*2:i*2+2])
|
||||
print '\x1b[33mcoverage: %s/%s (%d%%) tests passed.\x1b[0m' % (passed, count, passed*100/count)
|
||||
@@ -1,24 +1,25 @@
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
b
|
||||
c
|
||||
d
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
|
||||
|
||||
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
w
|
||||
x
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
w
|
||||
x
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
6 C
|
||||
8 ^^^^
|
||||
9 vvvv DL on line 11, expected: ACD_
|
||||
10 A
|
||||
@@ -12,14 +13,14 @@
|
||||
19 vvvv IL on line 21, expected: A_
|
||||
20 A
|
||||
|
||||
|
||||
22 ^^^^
|
||||
|
||||
23 vvvv IL on line 24, expected: _A
|
||||
24 A
|
||||
25 B
|
||||
26 ^^^^
|
||||
28 A
|
||||
27 vvvv DL on line 28, expected: B_
|
||||
|
||||
28 A
|
||||
29 B
|
||||
30 ^^^^
|
||||
31
|
||||
32
|
||||
32
|
||||
@@ -1,25 +1,25 @@
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
u
|
||||
v
|
||||
w
|
||||
x
|
||||
y
|
||||
z
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
o
|
||||
p
|
||||
q
|
||||
r
|
||||
s
|
||||
t
|
||||
u
|
||||
v
|
||||
w
|
||||
x
|
||||
y
|
||||
z
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
|
||||
11
|
||||
|
||||
11
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
efgh
|
||||
-------- set: wraparound ----------------------------------------------abcd
|
||||
efgh
|
||||
-------- unset: no wraparound -------------------------------------------abcd
|
||||
-------- unset: no wraparound -------------------------------------------abch
|
||||
this should be immediately below "no wraparound"
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
Test of autowrap, mixing control and print characters.
|
||||
|
||||
|
||||
The left/right margins should have letters in order:
|
||||
|
||||
|
||||
[3;21r[?6h[19;1HA[19;80Ha
|
||||
[18;80HaB[19;80HB b
|
||||
[19;80HC c[19;2HC
|
||||
[19;80H
|
||||
[18;1HD[18;80Hd[19;1HE[19;80He
|
||||
[18;80HeF[19;80HF f
|
||||
[19;80HG g[19;2HG
|
||||
[19;80H
|
||||
[18;1HH[18;80Hh[19;1HI[19;80Hi
|
||||
[18;80HiJ[19;80HJ j
|
||||
[19;80HK k[19;2HK
|
||||
[19;80H
|
||||
[18;1HL[18;80Hl[19;1HM[19;80Hm
|
||||
[18;80HmN[19;80HN n
|
||||
[19;80HO o[19;2HO
|
||||
[19;80H
|
||||
[18;1HP[18;80Hp[19;1HQ[19;80Hq
|
||||
[18;80HqR[19;80HR r
|
||||
[19;80HS s[19;2HS
|
||||
[19;80H
|
||||
[18;1HT[18;80Ht[19;1HU[19;80Hu
|
||||
[18;80HuV[19;80HV v
|
||||
[19;80HW w[19;2HW
|
||||
[19;80H
|
||||
[18;1HX[18;80Hx[19;1HY[19;80Hy
|
||||
[18;80HyZ[19;80HZ z
|
||||
[?6l[r[22;1HPush <RETURN>
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
Test of autowrap, mixing control and print characters.
|
||||
|
||||
I i
|
||||
J j
|
||||
K k
|
||||
L l
|
||||
M m
|
||||
N n
|
||||
O o
|
||||
P p
|
||||
Q q
|
||||
R r
|
||||
S s
|
||||
T t
|
||||
U u
|
||||
V v
|
||||
W w
|
||||
X x
|
||||
Y y
|
||||
Z z
|
||||
|
||||
Push <RETURN>
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+264
-196
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ import { Terminal } from './Terminal';
|
||||
import { MockViewport, MockCompositionHelper, MockRenderer } from './TestUtils.test';
|
||||
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { wcwidth } from 'common/CharWidth';
|
||||
|
||||
const INIT_COLS = 80;
|
||||
const INIT_ROWS = 24;
|
||||
@@ -750,10 +751,14 @@ describe('Terminal', () => {
|
||||
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
||||
term.buffer.x = term.cols - 1;
|
||||
term.wraparoundMode = false;
|
||||
const width = wcwidth((0xD800 - 0xD800) * 0x400 + i - 0xDC00 + 0x10000);
|
||||
if (width !== 1) {
|
||||
continue;
|
||||
}
|
||||
term.write('a' + high + String.fromCharCode(i));
|
||||
// auto wraparound mode should cut off the rest of the line
|
||||
expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql('a');
|
||||
expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars().length).eql(1);
|
||||
expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i));
|
||||
expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars().length).eql(2);
|
||||
expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql('');
|
||||
term.reset();
|
||||
}
|
||||
|
||||
+6
-48
@@ -1811,46 +1811,12 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
}
|
||||
|
||||
/**
|
||||
* ESC
|
||||
*/
|
||||
|
||||
/**
|
||||
* ESC D Index (IND is 0x84).
|
||||
*/
|
||||
public index(): void {
|
||||
this.buffer.y++;
|
||||
if (this.buffer.y > this.buffer.scrollBottom) {
|
||||
this.buffer.y--;
|
||||
this.scroll();
|
||||
}
|
||||
// If the end of the line is hit, prevent this action from wrapping around to the next line.
|
||||
if (this.buffer.x >= this.cols) {
|
||||
this.buffer.x--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ESC M Reverse Index (RI is 0x8d).
|
||||
*
|
||||
* Move the cursor up one row, inserting a new blank line if necessary.
|
||||
*/
|
||||
public reverseIndex(): void {
|
||||
if (this.buffer.y === this.buffer.scrollTop) {
|
||||
// possibly move the code below to term.reverseScroll();
|
||||
// test: echo -ne '\e[1;1H\e[44m\eM\e[0m'
|
||||
// blankLine(true) is xterm/linux behavior
|
||||
const scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop;
|
||||
this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1);
|
||||
this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.buffer.getBlankLine(this.eraseAttrData()));
|
||||
this.updateRange(this.buffer.scrollTop);
|
||||
this.updateRange(this.buffer.scrollBottom);
|
||||
} else {
|
||||
this.buffer.y--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ESC c Full Reset (RIS).
|
||||
* Reset terminal.
|
||||
* Note: Calling this directly from JS is synchronous but does not clear
|
||||
* input buffers and does not reset the parser, thus the terminal will
|
||||
* continue to apply pending input data.
|
||||
* If you need in band reset (synchronous with input data) consider
|
||||
* using DECSTR (soft reset, CSI ! p) or RIS instead (hard reset, ESC c).
|
||||
*/
|
||||
public reset(): void {
|
||||
/**
|
||||
@@ -1892,14 +1858,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ESC H Tab Set (HTS is 0x88).
|
||||
*/
|
||||
public tabSet(): void {
|
||||
this.buffer.tabs[this.buffer.x] = true;
|
||||
}
|
||||
|
||||
// TODO: Remove cancel function and cancelEvents option
|
||||
public cancel(ev: Event, force?: boolean): boolean {
|
||||
if (!this.options.cancelEvents && !force) {
|
||||
|
||||
+92
-112
@@ -1,45 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2016 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* This file contains integration tests for xterm.js.
|
||||
*/
|
||||
|
||||
import * as glob from 'glob';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as pty from 'node-pty';
|
||||
import { Terminal } from './Terminal';
|
||||
import { IViewport } from './Types';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
|
||||
import { IDisposable } from 'xterm';
|
||||
|
||||
class TestTerminal extends Terminal {
|
||||
innerWrite(): void { this._innerWrite(); }
|
||||
// all test files expect terminal in 80x25
|
||||
const COLS = 80;
|
||||
const ROWS = 25;
|
||||
|
||||
const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '..')});
|
||||
const SKIP_FILES = [
|
||||
't0070-DECSTBM_LF.in', // lineFeed not working correctly
|
||||
't0071-DECSTBM_IND.in',
|
||||
't0072-DECSTBM_NEL.in',
|
||||
't0075-DECSTBM_CUU_CUD.in',
|
||||
't0076-DECSTBM_IL_DL.in', // not working due to lineFeed
|
||||
't0077-DECSTBM_quirks.in',
|
||||
't0084-CBT.in',
|
||||
't0101-NLM.in',
|
||||
't0103-reverse_wrap.in',
|
||||
't0504-vim.in'
|
||||
];
|
||||
if (os.platform() === 'darwin') {
|
||||
// These are failing on macOS only (termios related?)
|
||||
SKIP_FILES.push(
|
||||
't0003-line_wrap.in',
|
||||
't0005-CR.in',
|
||||
't0009-NEL.in',
|
||||
't0503-zsh_ls_color.in'
|
||||
);
|
||||
}
|
||||
// filter skipFilenames
|
||||
const FILES = TESTFILES.filter(value => SKIP_FILES.indexOf(value.split('/').slice(-1)[0]) === -1);
|
||||
|
||||
let primitivePty: any;
|
||||
|
||||
// fake sychronous pty write - read
|
||||
// we just pipe the data from slave to master as a child program would do
|
||||
// pty.js opens pipe fds with O_NONBLOCK
|
||||
// just wait 10ms instead of setting fds to blocking mode
|
||||
function ptyWriteRead(data: string, cb: (result: string) => void): void {
|
||||
fs.writeSync(primitivePty.slave, data);
|
||||
setTimeout(() => {
|
||||
const b = new Buffer(64000);
|
||||
const bytes = fs.readSync(primitivePty.master, b, 0, 64000, null);
|
||||
cb(b.toString('utf8', 0, bytes));
|
||||
describe('Escape Sequence Files', function(): void {
|
||||
this.timeout(20000);
|
||||
|
||||
let ptyTerm: any;
|
||||
let slaveEnd: any;
|
||||
let term: Terminal;
|
||||
let customHandler: IDisposable | undefined;
|
||||
|
||||
before(() => {
|
||||
ptyTerm = (pty as any).open({cols: COLS, rows: ROWS});
|
||||
slaveEnd = ptyTerm._slave;
|
||||
term = new Terminal({cols: COLS, rows: ROWS});
|
||||
ptyTerm._master.on('data', (data: string) => term.write(data));
|
||||
});
|
||||
}
|
||||
|
||||
// make sure raw pty is at x=0 and has no pending data
|
||||
function ptyReset(cb: (result: string) => void): void {
|
||||
ptyWriteRead('\r\n', cb);
|
||||
}
|
||||
after(() => {
|
||||
ptyTerm._master.end();
|
||||
ptyTerm._master.destroy();
|
||||
});
|
||||
|
||||
FILES.forEach(filename => {
|
||||
it(filename.split('/').slice(-1)[0], async () => {
|
||||
// reset terminal and handler
|
||||
if (customHandler) {
|
||||
customHandler.dispose();
|
||||
}
|
||||
slaveEnd.write('\r\n');
|
||||
term.reset();
|
||||
slaveEnd.write('\x1bc\x1b[H');
|
||||
|
||||
// register handler to trigger viewport scraping, wait for it to finish
|
||||
let content = '';
|
||||
const OSC_CODE = 12345;
|
||||
await new Promise(resolve => {
|
||||
customHandler = term.addOscHandler(OSC_CODE, () => {
|
||||
// grab terminal viewport content
|
||||
content = terminalToString(term);
|
||||
resolve();
|
||||
return true;
|
||||
});
|
||||
// write file to slave
|
||||
slaveEnd.write(fs.readFileSync(filename, 'utf8'));
|
||||
// trigger custom sequence
|
||||
slaveEnd.write(`\x1b]${OSC_CODE};\x07`);
|
||||
});
|
||||
|
||||
// compare with expected output (right trimmed)
|
||||
const expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8');
|
||||
const expectedRightTrimmed = expected.split('\n').map(l => l.replace(/\s+$/, '')).join('\n');
|
||||
if (content !== expectedRightTrimmed) {
|
||||
throw new Error(formatError(fs.readFileSync(filename, 'utf8'), content, expected));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
/* debug helpers */
|
||||
// generate colorful noisy output to compare xterm and emulator cell states
|
||||
function formatError(input: string, output: string, expected: string): string {
|
||||
function addLineNumber(start: number, color: string): (s: string) => string {
|
||||
@@ -51,10 +112,10 @@ function formatError(input: string, output: string, expected: string): string {
|
||||
}
|
||||
const line80 = '12345678901234567890123456789012345678901234567890123456789012345678901234567890';
|
||||
let s = '';
|
||||
s += '\n\x1b[34m' + JSON.stringify(input);
|
||||
s += '\n\x1b[33m ' + line80 + '\n';
|
||||
s += `\n\x1b[34m${JSON.stringify(input)}`;
|
||||
s += `\n\x1b[33m ${line80}\n`;
|
||||
s += output.split('\n').map(addLineNumber(0, '\x1b[31m')).join('\n');
|
||||
s += '\n\x1b[33m ' + line80 + '\n';
|
||||
s += `\n\x1b[33m ${line80}\n`;
|
||||
s += expected.split('\n').map(addLineNumber(0, '\x1b[32m')).join('\n');
|
||||
return s;
|
||||
}
|
||||
@@ -64,10 +125,7 @@ function terminalToString(term: Terminal): string {
|
||||
let result = '';
|
||||
let lineText = '';
|
||||
for (let line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) {
|
||||
lineText = '';
|
||||
for (let cell = 0; cell < term.cols; ++cell) {
|
||||
lineText += term.buffer.lines.get(line).loadCell(cell, new CellData()).getChars() || WHITESPACE_CELL_CHAR;
|
||||
}
|
||||
lineText = term.buffer.lines.get(line).translateToString(true);
|
||||
// rtrim empty cells as xterm does
|
||||
lineText = lineText.replace(/\s+$/, '');
|
||||
result += lineText;
|
||||
@@ -75,81 +133,3 @@ function terminalToString(term: Terminal): string {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Skip tests on Windows since pty.open isn't supported
|
||||
if (os.platform() !== 'win32') {
|
||||
const consoleLog = console.log;
|
||||
|
||||
// expect files need terminal at 80x25!
|
||||
const cols = 80;
|
||||
const rows = 25;
|
||||
|
||||
/** some helpers for pty interaction */
|
||||
// we need a pty in between to get the termios decorations
|
||||
// for the basic test cases a raw pty device is enough
|
||||
primitivePty = (<any>pty).native.open(cols, rows);
|
||||
|
||||
/** tests */
|
||||
describe('xterm output comparison', function(): void {
|
||||
this.timeout(10000);
|
||||
let xterm: TestTerminal;
|
||||
|
||||
beforeEach(() => {
|
||||
xterm = new TestTerminal({ cols: cols, rows: rows });
|
||||
xterm.refresh = () => {};
|
||||
xterm.viewport = <IViewport>{
|
||||
syncScrollArea: () => {}
|
||||
};
|
||||
});
|
||||
|
||||
// omit stack trace for escape sequence files
|
||||
Error.stackTraceLimit = 0;
|
||||
const files = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '..')});
|
||||
// for (let i = 0; i < files.length; ++i) console.debug(i, files[i]);
|
||||
// only successful tests for now
|
||||
const skip = [
|
||||
10, 16, 17, 19, 32, 34, 35, 36, 39,
|
||||
40, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||
51, 52, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
63, 68
|
||||
];
|
||||
// These are failing on macOS only
|
||||
if (os.platform() === 'darwin') {
|
||||
skip.push(3, 7, 11, 67);
|
||||
}
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (skip.indexOf(i) >= 0) {
|
||||
continue;
|
||||
}
|
||||
((filename: string) => {
|
||||
const inFile = fs.readFileSync(filename, 'utf8');
|
||||
it(filename.split('/').slice(-1)[0], done => {
|
||||
ptyReset(() => {
|
||||
ptyWriteRead(inFile, fromPty => {
|
||||
// uncomment this to get log from terminal
|
||||
// console.log = function(){};
|
||||
|
||||
// Perform a synchronous .write(data)
|
||||
xterm.writeBuffer.push(fromPty);
|
||||
xterm.innerWrite();
|
||||
|
||||
const fromEmulator = terminalToString(xterm);
|
||||
console.log = consoleLog;
|
||||
const expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8');
|
||||
|
||||
// Some of the tests have whitespace on the right of lines, we trim all the linex
|
||||
// from xterm.js so ignore this for now at least.
|
||||
const expectedRightTrimmed = expected.split('\n').map(l => l.replace(/\s+$/, '')).join('\n');
|
||||
if (fromEmulator !== expectedRightTrimmed) {
|
||||
// uncomment to get noisy output
|
||||
throw new Error(formatError(inFile, fromEmulator, expected));
|
||||
// throw new Error('mismatch');
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
})(files[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+2
-10
@@ -6,7 +6,7 @@
|
||||
import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBrowser, ITerminalOptions, ILinkifier, ILinkMatcherOptions } from './Types';
|
||||
import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener } from 'common/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset } from 'common/Types';
|
||||
import { Buffer } from 'common/buffer/Buffer';
|
||||
import * as Browser from 'common/Platform';
|
||||
import { IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm';
|
||||
@@ -295,21 +295,12 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
||||
addDisposableListener(type: string, handler: XtermListener): IDisposable {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
tabSet(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
handler(data: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
handleTitle(title: string): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
index(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
reverseIndex(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
export class MockBuffer implements IBuffer {
|
||||
@@ -329,6 +320,7 @@ export class MockBuffer implements IBuffer {
|
||||
scrollTop: number;
|
||||
savedY: number;
|
||||
savedX: number;
|
||||
savedCharset: ICharset | null;
|
||||
savedCurAttrData = new AttributeData();
|
||||
translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string {
|
||||
return Buffer.prototype.translateBufferLineToString.apply(this, arguments);
|
||||
|
||||
Vendored
+1
-3
@@ -70,10 +70,7 @@ export interface IInputHandlingTerminal {
|
||||
showCursor(): void;
|
||||
refresh(start: number, end: number): void;
|
||||
error(text: string, data?: any): void;
|
||||
tabSet(): void;
|
||||
handleTitle(title: string): void;
|
||||
index(): void;
|
||||
reverseIndex(): void;
|
||||
}
|
||||
|
||||
export interface IViewport extends IDisposable {
|
||||
@@ -169,6 +166,7 @@ export interface IInputHandler {
|
||||
ESC |
|
||||
ESC }
|
||||
ESC ~ */ setgLevel(level: number): void;
|
||||
/** ESC # 8 */ screenAlignmentPattern(): void;
|
||||
}
|
||||
|
||||
export interface ILinkMatcher {
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
|
||||
import { CircularList, IInsertEvent } from 'common/CircularList';
|
||||
import { IBuffer, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult } from 'common/buffer/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData } from 'common/Types';
|
||||
import { IBufferLine, ICellData, IAttributeData, ICharset } from 'common/Types';
|
||||
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from 'common/buffer/Constants';
|
||||
import { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from 'common/buffer/BufferReflow';
|
||||
import { Marker } from 'common/buffer/Marker';
|
||||
import { IOptionsService, IBufferService } from 'common/services/Services';
|
||||
import { DEFAULT_CHARSET } from 'common/data/Charsets';
|
||||
|
||||
export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
|
||||
|
||||
@@ -35,6 +36,7 @@ export class Buffer implements IBuffer {
|
||||
public savedY: number = 0;
|
||||
public savedX: number = 0;
|
||||
public savedCurAttrData = DEFAULT_ATTR_DATA.clone();
|
||||
public savedCharset: ICharset | null = DEFAULT_CHARSET;
|
||||
public markers: Marker[] = [];
|
||||
private _nullCell: ICellData = CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
||||
private _whitespaceCell: ICellData = CellData.fromCharData([0, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE]);
|
||||
|
||||
Vendored
+2
-1
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IAttributeData, ICircularList, IBufferLine, ICellData, IMarker } from 'common/Types';
|
||||
import { IAttributeData, ICircularList, IBufferLine, ICellData, IMarker, ICharset } from 'common/Types';
|
||||
import { IEvent } from 'common/EventEmitter';
|
||||
|
||||
// BufferIndex denotes a position in the buffer: [rowIndex, colIndex]
|
||||
@@ -31,6 +31,7 @@ export interface IBuffer {
|
||||
hasScrollback: boolean;
|
||||
savedY: number;
|
||||
savedX: number;
|
||||
savedCharset: ICharset | null;
|
||||
savedCurAttrData: IAttributeData;
|
||||
isCursorInViewport: boolean;
|
||||
markers: IMarker[];
|
||||
|
||||
@@ -466,10 +466,10 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
}
|
||||
break;
|
||||
case ParserAction.EXECUTE:
|
||||
this.precedingCodepoint = 0;
|
||||
callback = this._executeHandlers[code];
|
||||
if (callback) callback();
|
||||
else this._executeHandlerFb(code);
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
case ParserAction.IGNORE:
|
||||
break;
|
||||
@@ -488,10 +488,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
// inject values: currently not implemented
|
||||
break;
|
||||
case ParserAction.CSI_DISPATCH:
|
||||
// dont reset preceding codepoint for REP itself
|
||||
if (code !== 98) { // 'b'
|
||||
this.precedingCodepoint = 0;
|
||||
}
|
||||
// Trigger CSI Handler
|
||||
const handlers = this._csiHandlers[code];
|
||||
let j = handlers ? handlers.length - 1 : -1;
|
||||
@@ -504,6 +500,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
if (j < 0) {
|
||||
this._csiHandlerFb(collect, params, code);
|
||||
}
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
case ParserAction.PARAM:
|
||||
// inner loop: digits (0x30 - 0x39) and ; (0x3b) and : (0x3a)
|
||||
@@ -529,10 +526,10 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
collect += String.fromCharCode(code);
|
||||
break;
|
||||
case ParserAction.ESC_DISPATCH:
|
||||
this.precedingCodepoint = 0;
|
||||
callback = this._escHandlers[collect + String.fromCharCode(code)];
|
||||
if (callback) callback(collect, code);
|
||||
else this._escHandlerFb(collect, code);
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
case ParserAction.CLEAR:
|
||||
osc = '';
|
||||
@@ -541,7 +538,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
collect = '';
|
||||
break;
|
||||
case ParserAction.DCS_HOOK:
|
||||
this.precedingCodepoint = 0;
|
||||
dcsHandler = this._dcsHandlers[collect + String.fromCharCode(code)];
|
||||
if (!dcsHandler) dcsHandler = this._dcsHandlerFb;
|
||||
dcsHandler.hook(collect, params, code);
|
||||
@@ -569,6 +565,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
params.reset();
|
||||
params.addParam(0); // ZDM
|
||||
collect = '';
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
case ParserAction.OSC_START:
|
||||
osc = '';
|
||||
@@ -584,7 +581,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
}
|
||||
break;
|
||||
case ParserAction.OSC_END:
|
||||
this.precedingCodepoint = 0;
|
||||
if (osc && code !== 0x18 && code !== 0x1a) {
|
||||
// NOTE: OSC subparsing is not part of the original parser
|
||||
// we do basic identifier parsing here to offer a jump table for OSC as well
|
||||
@@ -616,6 +612,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
params.reset();
|
||||
params.addParam(0); // ZDM
|
||||
collect = '';
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
}
|
||||
currentState = transition & TableAccess.TRANSITION_STATE_MASK;
|
||||
|
||||
Reference in New Issue
Block a user