Use jsdoc/multiline-blocks instead of multiline-comment-style

Replace multiline-comment-style (starred-block), which also forces
multiline // comments into block comments, with jsdoc/multiline-blocks.
That rule only enforces starred JSDoc layout for /** blocks (no text on
the opening line) and leaves multiline // comments unchanged for
internal documentation.

Fix multiline JSDoc in Types.ts.

Fixes #5899

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-05-26 20:32:23 +00:00
co-authored by Daniel Imms
parent 4ec85e67ba
commit df3422fb0b
138 changed files with 1834 additions and 3028 deletions
+2 -4
View File
@@ -52,10 +52,8 @@ export class CircularList<T> extends Disposable implements ICircularList<T> {
return;
}
/*
* Reconstruct array, starting at index 0. Only transfer values from the
* indexes 0 to length.
*/
// Reconstruct array, starting at index 0. Only transfer values from the
// indexes 0 to length.
const newArray = new Array<T | undefined>(newMaxLength);
for (let i = 0; i < Math.min(newMaxLength, this.length); i++) {
newArray[i] = this._array[this._getCyclicIndex(i)];
+12 -22
View File
@@ -27,11 +27,9 @@ export namespace channels {
}
export function toRgba(r: number, g: number, b: number, a: number = 0xFF): number {
/*
* Note: The aggregated number is RGBA32 (BE), thus needs to be converted to ABGR32
* on LE systems, before it can be used for direct 32-bit buffer writes.
* >>> 0 forces an unsigned int
*/
// Note: The aggregated number is RGBA32 (BE), thus needs to be converted to ABGR32
// on LE systems, before it can be used for direct 32-bit buffer writes.
// >>> 0 forces an unsigned int
return (r << 24 | g << 16 | b << 8 | a) >>> 0;
}
@@ -199,10 +197,8 @@ export namespace css {
throw new Error('css.toColor: Unsupported css format');
}
/*
* Validate the color using canvas fillStyle
* See https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles
*/
// Validate the color using canvas fillStyle
// See https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles
$ctx.fillStyle = $litmusColor;
$ctx.fillStyle = css;
if (typeof $ctx.fillStyle !== 'string') {
@@ -217,11 +213,9 @@ export namespace css {
throw new Error('css.toColor: Unsupported css format');
}
/*
* Extract the color from the canvas' fillStyle property which exposes the color value in rgba()
* format
* See https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
*/
// Extract the color from the canvas' fillStyle property which exposes the color value in rgba()
// format
// See https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
return {
rgba: channels.toRgba($r, $g, $b, $a),
css
@@ -327,10 +321,8 @@ export namespace rgba {
}
export function reduceLuminance(bgRgba: number, fgRgba: number, ratio: number): number {
/*
* This is a naive but fast approach to reducing luminance as converting to
* HSL and back is expensive
*/
// This is a naive but fast approach to reducing luminance as converting to
// HSL and back is expensive
const bgR = (bgRgba >> 24) & 0xFF;
const bgG = (bgRgba >> 16) & 0xFF;
const bgB = (bgRgba >> 8) & 0xFF;
@@ -349,10 +341,8 @@ export namespace rgba {
}
export function increaseLuminance(bgRgba: number, fgRgba: number, ratio: number): number {
/*
* This is a naive but fast approach to increasing luminance as converting to
* HSL and back is expensive
*/
// This is a naive but fast approach to increasing luminance as converting to
// HSL and back is expensive
const bgR = (bgRgba >> 24) & 0xFF;
const bgG = (bgRgba >> 16) & 0xFF;
const bgB = (bgRgba >> 8) & 0xFF;
+2 -4
View File
@@ -176,10 +176,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
x = Math.max(x, BufferServiceConstants.MINIMUM_COLS);
y = Math.max(y, BufferServiceConstants.MINIMUM_ROWS);
/*
* Flush pending writes before resize to avoid race conditions where async
* writes are processed with incorrect dimensions
*/
// Flush pending writes before resize to avoid race conditions where async
// writes are processed with incorrect dimensions
this._writeBuffer.flushSync();
this._bufferService.resize(x, y);
+4 -8
View File
@@ -613,10 +613,8 @@ describe('InputHandler', () => {
await inputHandler.parseP('a'.repeat(bufferService.cols + 9)); // line 1 and 2
for (let i = 3; i < bufferService.rows; ++i) await inputHandler.parseP('a'.repeat(bufferService.cols));
/*
* params[1] left and above with wrap
* confirm precondition that line 2 is wrapped
*/
// params[1] left and above with wrap
// confirm precondition that line 2 is wrapped
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, true);
bufferService.buffer.y = 2;
bufferService.buffer.x = 40;
@@ -630,10 +628,8 @@ describe('InputHandler', () => {
await inputHandler.parseP('a'.repeat(bufferService.cols + 9)); // line 1 and 2
for (let i = 3; i < bufferService.rows; ++i) await inputHandler.parseP('a'.repeat(bufferService.cols));
/*
* params[1] left and above with wrap
* confirm precondition that line 2 is wrapped
*/
// params[1] left and above with wrap
// confirm precondition that line 2 is wrapped
assert.equal(bufferService.buffer.lines.get(2)!.isWrapped, true);
bufferService.buffer.y = 1;
bufferService.buffer.x = 90; // Cursor is beyond last column
+121 -203
View File
@@ -33,12 +33,10 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-':
/**
* Document xterm VT features here that are currently unsupported
*/
/*
* @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys."
* @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String."
* @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data."
* @vt: #N OSC 1 "Set Icon Name" "OSC 1 ; Pt BEL" "Set icon name."
*/
// @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys."
// @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String."
// @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data."
// @vt: #N OSC 1 "Set Icon Name" "OSC 1 ; Pt BEL" "Set icon name."
/**
* Max length of the UTF32 input buffer. Real memory consumption is 4 times higher.
@@ -290,17 +288,13 @@ export class InputHandler extends Disposable implements IInputHandler {
this._parser.registerOscHandler(1, new OscHandler(data => this.setIconName(data)));
// 2 - title
this._parser.registerOscHandler(2, new OscHandler(data => this.setTitle(data)));
/*
* 3 - set property X in the form "prop=value"
* 4 - Change Color Number
*/
// 3 - set property X in the form "prop=value"
// 4 - Change Color Number
this._parser.registerOscHandler(4, new OscHandler(data => this.setOrReportIndexedColor(data)));
/*
* 5 - Change Special Color Number
* 6 - Enable/disable Special Color Number c
* 7 - current directory? (not in xterm spec, see https://gitlab.com/gnachman/iterm2/issues/3939)
* 8 - create hyperlink (not in xterm spec, see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)
*/
// 5 - Change Special Color Number
// 6 - Enable/disable Special Color Number c
// 7 - current directory? (not in xterm spec, see https://gitlab.com/gnachman/iterm2/issues/3939)
// 8 - create hyperlink (not in xterm spec, see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)
this._parser.registerOscHandler(8, new OscHandler(data => this.setHyperlink(data)));
// 10 - Change VT100 text foreground color to Pt.
this._parser.registerOscHandler(10, new OscHandler(data => this.setOrReportFgColor(data)));
@@ -308,40 +302,34 @@ export class InputHandler extends Disposable implements IInputHandler {
this._parser.registerOscHandler(11, new OscHandler(data => this.setOrReportBgColor(data)));
// 12 - Change text cursor color to Pt.
this._parser.registerOscHandler(12, new OscHandler(data => this.setOrReportCursorColor(data)));
/*
* 13 - Change mouse foreground color to Pt.
* 14 - Change mouse background color to Pt.
* 15 - Change Tektronix foreground color to Pt.
* 16 - Change Tektronix background color to Pt.
* 17 - Change highlight background color to Pt.
* 18 - Change Tektronix cursor color to Pt.
* 19 - Change highlight foreground color to Pt.
* 46 - Change Log File to Pt.
* 50 - Set Font to Pt.
* 51 - reserved for Emacs shell.
* 52 - Manipulate Selection Data.
* 104 ; c - Reset Color Number c.
*/
// 13 - Change mouse foreground color to Pt.
// 14 - Change mouse background color to Pt.
// 15 - Change Tektronix foreground color to Pt.
// 16 - Change Tektronix background color to Pt.
// 17 - Change highlight background color to Pt.
// 18 - Change Tektronix cursor color to Pt.
// 19 - Change highlight foreground color to Pt.
// 46 - Change Log File to Pt.
// 50 - Set Font to Pt.
// 51 - reserved for Emacs shell.
// 52 - Manipulate Selection Data.
// 104 ; c - Reset Color Number c.
this._parser.registerOscHandler(104, new OscHandler(data => this.restoreIndexedColor(data)));
/*
* 105 ; c - Reset Special Color Number c.
* 106 ; c; f - Enable/disable Special Color Number c.
* 110 - Reset VT100 text foreground color.
*/
// 105 ; c - Reset Special Color Number c.
// 106 ; c; f - Enable/disable Special Color Number c.
// 110 - Reset VT100 text foreground color.
this._parser.registerOscHandler(110, new OscHandler(data => this.restoreFgColor(data)));
// 111 - Reset VT100 text background color.
this._parser.registerOscHandler(111, new OscHandler(data => this.restoreBgColor(data)));
// 112 - Reset text cursor color.
this._parser.registerOscHandler(112, new OscHandler(data => this.restoreCursorColor(data)));
/*
* 113 - Reset mouse foreground color.
* 114 - Reset mouse background color.
* 115 - Reset Tektronix foreground color.
* 116 - Reset Tektronix background color.
* 117 - Reset highlight color.
* 118 - Reset Tektronix cursor color.
* 119 - Reset highlight foreground color.
*/
// 113 - Reset mouse foreground color.
// 114 - Reset mouse background color.
// 115 - Reset Tektronix foreground color.
// 116 - Reset Tektronix background color.
// 117 - Reset highlight color.
// 118 - Reset Tektronix cursor color.
// 119 - Reset highlight foreground color.
/**
* ESC handlers
@@ -478,10 +466,8 @@ export class InputHandler extends Disposable implements IInputHandler {
}
}
/*
* Clear the dirty row service so we know which lines changed as a result of parsing
* Important: do not clear between async calls, otherwise we lost pending update information.
*/
// Clear the dirty row service so we know which lines changed as a result of parsing
// Important: do not clear between async calls, otherwise we lost pending update information.
if (!wasPaused) {
this._dirtyRowTracker.clearRange();
}
@@ -516,10 +502,8 @@ export class InputHandler extends Disposable implements IInputHandler {
this._onCursorMove.fire();
}
/*
* Refresh any dirty rows accumulated as part of parsing, fire only for rows within the
* _viewport_ which is relative to ydisp, not relative to ybase.
*/
// Refresh any dirty rows accumulated as part of parsing, fire only for rows within the
// _viewport_ which is relative to ydisp, not relative to ybase.
const viewportEnd = this._dirtyRowTracker.end + (this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
const viewportStart = this._dirtyRowTracker.start + (this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
if (viewportStart < this._bufferService.rows) {
@@ -541,10 +525,8 @@ export class InputHandler extends Disposable implements IInputHandler {
const curAttr = this._curAttrData;
let bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y);
/*
* Defensive check: bufferRow can be undefined if a resize occurred mid-write due to async
* scheduling gaps in WriteBuffer. See https://github.com/xtermjs/xterm.js/issues/5597
*/
// Defensive check: bufferRow can be undefined if a resize occurred mid-write due to async
// scheduling gaps in WriteBuffer. See https://github.com/xtermjs/xterm.js/issues/5597
if (!bufferRow) {
return;
}
@@ -560,19 +542,15 @@ export class InputHandler extends Disposable implements IInputHandler {
for (let pos = start; pos < end; ++pos) {
code = data[pos];
/*
* Soft hyphen's (U+00AD) behavior is ambiguous and differs across terminals. We opt to treat
* it as a zero-width hint to text layout engines and simply ignore it.
*/
// Soft hyphen's (U+00AD) behavior is ambiguous and differs across terminals. We opt to treat
// it as a zero-width hint to text layout engines and simply ignore it.
if (code === 0xAD) {
continue;
}
/*
* get charset replacement character
* charset is only defined for ASCII, therefore we only
* search for an replacement char if code < 127
*/
// get charset replacement character
// charset is only defined for ASCII, therefore we only
// search for an replacement char if code < 127
if (code < 127 && charset) {
const ch = charset[String.fromCharCode(code)];
if (ch) {
@@ -593,16 +571,12 @@ export class InputHandler extends Disposable implements IInputHandler {
this._oscLinkService.addLineToLink(this._getCurrentLinkId(), this._activeBuffer.ybase + this._activeBuffer.y);
}
/*
* goto next line if ch would overflow
* NOTE: To avoid costly width checks here,
* the terminal does not allow a cols < 2.
*/
// goto next line if ch would overflow
// NOTE: To avoid costly width checks here,
// the terminal does not allow a cols < 2.
if (this._activeBuffer.x + chWidth - oldWidth > cols) {
/*
* autowrap - DECAWM
* automatically wraps to the beginning of the next line
*/
// autowrap - DECAWM
// automatically wraps to the beginning of the next line
if (wraparoundMode) {
const oldRow = bufferRow;
let oldCol = this._activeBuffer.x - oldWidth;
@@ -615,10 +589,8 @@ export class InputHandler extends Disposable implements IInputHandler {
if (this._activeBuffer.y >= this._bufferService.rows) {
this._activeBuffer.y = this._bufferService.rows - 1;
}
/*
* The line already exists (eg. the initial viewport), mark it as a
* wrapped line
*/
// The line already exists (eg. the initial viewport), mark it as a
// wrapped line
this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = true;
}
// row changed, get it again
@@ -627,10 +599,8 @@ export class InputHandler extends Disposable implements IInputHandler {
return;
}
if (oldWidth > 0 && bufferRow instanceof BufferLine) {
/*
* Combining character widens 1 column to 2.
* Move old character to next line.
*/
// Combining character widens 1 column to 2.
// Move old character to next line.
bufferRow.copyCellsFrom(oldRow as BufferLine,
oldCol, 0, oldWidth, false);
}
@@ -641,28 +611,22 @@ export class InputHandler extends Disposable implements IInputHandler {
} else {
this._activeBuffer.x = cols - 1;
if (chWidth === 2) {
/*
* FIXME: check for xterm behavior
* What to do here? We got a wide char that does not fit into last cell
*/
// FIXME: check for xterm behavior
// What to do here? We got a wide char that does not fit into last cell
continue;
}
}
}
/*
* insert combining char at last cursor position
* this._activeBuffer.x should never be 0 for a combining char
* since they always follow a cell consuming char
* therefore we can test for this._activeBuffer.x to avoid overflow left
*/
// insert combining char at last cursor position
// this._activeBuffer.x should never be 0 for a combining char
// since they always follow a cell consuming char
// therefore we can test for this._activeBuffer.x to avoid overflow left
if (shouldJoin && this._activeBuffer.x) {
const offset = bufferRow.getWidth(this._activeBuffer.x - 1) ? 1 : 2;
/*
* if empty cell after fullwidth, need to go 2 cells back
* it is save to step 2 cells back here
* since an empty cell is only set by fullwidth chars
*/
// if empty cell after fullwidth, need to go 2 cells back
// it is save to step 2 cells back here
// since an empty cell is only set by fullwidth chars
bufferRow.addCodepointToCell(this._activeBuffer.x - offset,
code, chWidth);
for (let delta = chWidth - oldWidth; --delta >= 0;) {
@@ -675,11 +639,9 @@ export class InputHandler extends Disposable implements IInputHandler {
if (insertMode) {
// right shift cells according to the width
bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr));
/*
* test last cell - since the last cell has only room for
* a halfwidth char any fullwidth shifted there is lost
* and will be set to empty cell
*/
// test last cell - since the last cell has only room for
// a halfwidth char any fullwidth shifted there is lost
// and will be set to empty cell
if (bufferRow.getWidth(cols - 1) === 2) {
bufferRow.setCellFromCodepoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr);
}
@@ -688,11 +650,9 @@ export class InputHandler extends Disposable implements IInputHandler {
// write current char to buffer and advance cursor
bufferRow.setCellFromCodepoint(this._activeBuffer.x++, code, chWidth, curAttr);
/*
* fullwidth char - also set next cell to placeholder stub and advance cursor
* for graphemes bigger than fullwidth we can simply loop to zero
* we already made sure above, that this._activeBuffer.x + chWidth will not overflow right
*/
// fullwidth char - also set next cell to placeholder stub and advance cursor
// for graphemes bigger than fullwidth we can simply loop to zero
// we already made sure above, that this._activeBuffer.x + chWidth will not overflow right
if (chWidth > 0) {
while (--chWidth) {
// other than a regular empty cell a cell following a wide char has no width
@@ -790,13 +750,11 @@ export class InputHandler extends Disposable implements IInputHandler {
} else if (this._activeBuffer.y >= this._bufferService.rows) {
this._activeBuffer.y = this._bufferService.rows - 1;
} else {
/*
* There was an explicit line feed (not just a carriage return), so clear the wrapped state of
* the line. This is particularly important on conpty/Windows where revisiting lines to
* reprint is common, especially on resize. Note that the windowsMode wrapped line heuristics
* can mess with this so windowsMode should be disabled, which is recommended on Windows build
* 21376 and above.
*/
// There was an explicit line feed (not just a carriage return), so clear the wrapped state of
// the line. This is particularly important on conpty/Windows where revisiting lines to
// reprint is common, especially on resize. Note that the windowsMode wrapped line heuristics
// can mess with this so windowsMode should be disabled, which is recommended on Windows build
// 21376 and above.
this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = false;
}
// If the end of the line is hit, prevent this action from wrapping around to the next line.
@@ -841,11 +799,9 @@ export class InputHandler extends Disposable implements IInputHandler {
return true;
}
/*
* reverse wrap-around is enabled
* other than for normal operation mode, reverse wrap-around allows the cursor
* to be at x=cols to be able to address the last cell of a row by BS
*/
// reverse wrap-around is enabled
// other than for normal operation mode, reverse wrap-around allows the cursor
// to be at x=cols to be able to address the last cell of a row by BS
this._restrictCursor(this._bufferService.cols);
if (this._activeBuffer.x > 0) {
@@ -866,21 +822,17 @@ export class InputHandler extends Disposable implements IInputHandler {
this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = false;
this._activeBuffer.y--;
this._activeBuffer.x = this._bufferService.cols - 1;
/*
* find last taken cell - last cell can have 3 different states:
* - hasContent(true) + hasWidth(1): narrow char - we are done
* - hasWidth(0): second part of wide char - we are done
* - hasContent(false) + hasWidth(1): empty cell due to early wrapping wide char, go one
* cell further back
*/
// find last taken cell - last cell can have 3 different states:
// - hasContent(true) + hasWidth(1): narrow char - we are done
// - hasWidth(0): second part of wide char - we are done
// - hasContent(false) + hasWidth(1): empty cell due to early wrapping wide char, go one
// cell further back
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
if (line.hasWidth(this._activeBuffer.x) && !line.hasContent(this._activeBuffer.x)) {
this._activeBuffer.x--;
/*
* We do this only once, since width=1 + hasContent=false currently happens only once
* before early wrapping of a wide char.
* This needs to be fixed once we support graphemes taking more than 2 cells.
*/
// We do this only once, since width=1 + hasContent=false currently happens only once
// before early wrapping of a wide char.
// This needs to be fixed once we support graphemes taking more than 2 cells.
}
}
}
@@ -961,10 +913,8 @@ export class InputHandler extends Disposable implements IInputHandler {
* Set relative cursor position.
*/
private _moveCursor(x: number, y: number): void {
/*
* for relative changes we have to make sure we are within 0 .. cols/rows - 1
* before calculating the new position
*/
// for relative changes we have to make sure we are within 0 .. cols/rows - 1
// before calculating the new position
this._restrictCursor();
this._setCursor(this._activeBuffer.x + x, this._activeBuffer.y + y);
}
@@ -1404,10 +1354,8 @@ export class InputHandler extends Disposable implements IInputHandler {
const scrollBottomRowsOffset = this._bufferService.rows - 1 - this._activeBuffer.scrollBottom;
const scrollBottomAbsolute = this._bufferService.rows - 1 + this._activeBuffer.ybase - scrollBottomRowsOffset + 1;
while (param--) {
/*
* test: echo -e '\e[44m\e[1L\e[0m'
* blankLine(true) - xterm/linux behavior
*/
// test: echo -e '\e[44m\e[1L\e[0m'
// blankLine(true) - xterm/linux behavior
this._activeBuffer.lines.splice(scrollBottomAbsolute - 1, 1);
this._activeBuffer.lines.splice(row, 0, this._activeBuffer.getBlankLine(this._eraseAttrData()));
}
@@ -1440,10 +1388,8 @@ export class InputHandler extends Disposable implements IInputHandler {
j = this._bufferService.rows - 1 - this._activeBuffer.scrollBottom;
j = this._bufferService.rows - 1 + this._activeBuffer.ybase - j;
while (param--) {
/*
* test: echo -e '\e[44m\e[1M\e[0m'
* blankLine(true) - xterm/linux behavior
*/
// test: echo -e '\e[44m\e[1M\e[0m'
// blankLine(true) - xterm/linux behavior
this._activeBuffer.lines.splice(row, 1);
this._activeBuffer.lines.splice(j, 0, this._activeBuffer.getBlankLine(this._eraseAttrData()));
}
@@ -1791,20 +1737,16 @@ export class InputHandler extends Disposable implements IInputHandler {
if (params.params[0] > 0) {
return true;
}
/*
* xterm and urxvt
* seem to spit this
* out around ~370 times (?).
*/
// xterm and urxvt
// seem to spit this
// out around ~370 times (?).
if (this._is('xterm')) {
this._coreService.triggerDataEvent(C0.ESC + '[>0;276;0c');
} else if (this._is('rxvt-unicode')) {
this._coreService.triggerDataEvent(C0.ESC + '[>85;95;0c');
} else if (this._is('linux')) {
/*
* not supported by linux console.
* linux console echoes parameters.
*/
// not supported by linux console.
// linux console echoes parameters.
this._coreService.triggerDataEvent(params.params[0] + 'c');
} else if (this._is('screen')) {
this._coreService.triggerDataEvent(C0.ESC + '[>83;40003;0c');
@@ -2037,17 +1979,13 @@ export class InputHandler extends Disposable implements IInputHandler {
this._mouseStateService.activeProtocol = 'DRAG';
break;
case 1003: // any event mouse
/*
* any event - sends motion events,
* even if there is no button held down.
*/
// any event - sends motion events,
// even if there is no button held down.
this._mouseStateService.activeProtocol = 'ANY';
break;
case 1004: // send focusin/focusout events
/*
* focusin: ^[[I
* focusout: ^[[O
*/
// focusin: ^[[I
// focusout: ^[[O
this._coreService.decPrivateModes.sendFocus = true;
this._onRequestSendFocus.fire();
break;
@@ -2470,12 +2408,10 @@ export class InputHandler extends Disposable implements IInputHandler {
* Returns advance for params index.
*/
private _extractColor(params: IParams, pos: number, attr: IAttributeData): number {
/*
* normalize params
* meaning: [target, CM, ign, val, val, val]
* RGB : [ 38/48, 2, ign, r, g, b]
* P256 : [ 38/48, 5, ign, v, ign, ign]
*/
// normalize params
// meaning: [target, CM, ign, val, val, val]
// RGB : [ 38/48, 2, ign, r, g, b]
// P256 : [ 38/48, 5, ign, v, ign, ign]
const accu = [0, 0, -1, 0, 0, 0];
// alignment placeholder for non color space sequences
@@ -2541,10 +2477,8 @@ export class InputHandler extends Disposable implements IInputHandler {
* 4:5 - dashed underline
*/
private _processUnderline(style: number, attr: IAttributeData): void {
/*
* treat extended attrs as immutable, thus always clone from old one
* this is needed since the buffer only holds references to it
*/
// treat extended attrs as immutable, thus always clone from old one
// this is needed since the buffer only holds references to it
attr.extended = attr.extended.clone();
// default to 1 == single underline
@@ -2567,10 +2501,8 @@ export class InputHandler extends Disposable implements IInputHandler {
attr.fg = DEFAULT_ATTR_DATA.fg;
attr.bg = DEFAULT_ATTR_DATA.bg;
attr.extended = attr.extended.clone();
/*
* Reset underline style and color. Note that we don't want to reset other
* fields such as the url id.
*/
// Reset underline style and color. Note that we don't want to reset other
// fields such as the url id.
attr.extended.underlineStyle = UnderlineStyle.NONE;
attr.extended.underlineColor &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
attr.updateExtended();
@@ -2709,10 +2641,8 @@ export class InputHandler extends Disposable implements IInputHandler {
// blink
attr.fg |= FgFlags.BLINK;
} else if (p === 7) {
/*
* inverse and positive
* test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m'
*/
// inverse and positive
// test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m'
attr.fg |= FgFlags.INVERSE;
} else if (p === 8) {
// invisible
@@ -2826,10 +2756,8 @@ export class InputHandler extends Disposable implements IInputHandler {
// @vt: #P[Only CPR is supported.] CSI DECDSR "DEC Device Status Report" "CSI ? Ps n" "Only CPR is supported (same as DSR)."
public deviceStatusPrivate(params: IParams): boolean {
/*
* modern xterm doesnt seem to
* respond to any of these except ?6, 6, and 5
*/
// modern xterm doesnt seem to
// respond to any of these except ?6, 6, and 5
switch (params.params[0]) {
case 6:
// cursor position
@@ -2838,28 +2766,20 @@ export class InputHandler extends Disposable implements IInputHandler {
this._coreService.triggerDataEvent(`${C0.ESC}[?${y};${x}R`);
break;
case 15:
/*
* no printer
* this.handler(C0.ESC + '[?11n');
*/
// no printer
// this.handler(C0.ESC + '[?11n');
break;
case 25:
/*
* dont support user defined keys
* this.handler(C0.ESC + '[?21n');
*/
// dont support user defined keys
// this.handler(C0.ESC + '[?21n');
break;
case 26:
/*
* north american keyboard
* this.handler(C0.ESC + '[?27;1;0;0n');
*/
// north american keyboard
// this.handler(C0.ESC + '[?27;1;0;0n');
break;
case 53:
/*
* no dec locator/mouse
* this.handler(C0.ESC + '[?50n');
*/
// no dec locator/mouse
// this.handler(C0.ESC + '[?50n');
break;
case 996:
// color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
@@ -3481,11 +3401,9 @@ export class InputHandler extends Disposable implements IInputHandler {
public reverseIndex(): boolean {
this._restrictCursor();
if (this._activeBuffer.y === this._activeBuffer.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
*/
// 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._activeBuffer.scrollBottom - this._activeBuffer.scrollTop;
this._activeBuffer.lines.shiftElements(this._activeBuffer.ybase + this._activeBuffer.y, scrollRegionHeight, 1);
this._activeBuffer.lines.set(this._activeBuffer.ybase + this._activeBuffer.y, this._activeBuffer.getBlankLine(this._eraseAttrData()));
+8 -14
View File
@@ -9,18 +9,14 @@ interface INavigator {
platform: string;
}
/*
* We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
* we want this module to live in common.
*/
// We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
// we want this module to live in common.
declare const navigator: INavigator;
declare const process: unknown;
/*
* navigator.userAgent is also checked here because bundling with the process module can cause
* issues otherwise. Note that navigator exists in Node.js 21+ but the userAgent is
* "Node.js/<version>".
*/
// navigator.userAgent is also checked here because bundling with the process module can cause
// issues otherwise. Note that navigator exists in Node.js 21+ but the userAgent is
// "Node.js/<version>".
export const isNode = (typeof process !== 'undefined' && 'title' in (process as any) && (typeof navigator === 'undefined' || navigator.userAgent.startsWith('Node.js/'))) ? true : false;
const userAgent = (isNode) ? 'node' : navigator.userAgent;
const platform = (isNode) ? 'node' : navigator.platform;
@@ -48,11 +44,9 @@ export function getSafariVersion(): number {
return parseInt(majorVersion[1]);
}
/*
* Find the users platform. We use this to interpret the meta key
* and ISO third level shifts.
* http://stackoverflow.com/q/19877924/577598
*/
// Find the users platform. We use this to interpret the meta key
// and ISO third level shifts.
// http://stackoverflow.com/q/19877924/577598
export const isMac = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'].includes(platform);
export const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(platform);
export const isLinux = platform.indexOf('Linux') >= 0;
+2 -4
View File
@@ -191,10 +191,8 @@ export class SortedList<T> {
return mid;
}
}
/*
* key not in list
* still return closest min (also used as insert position)
*/
// key not in list
// still return closest min (also used as insert position)
return min;
}
}
+7 -13
View File
@@ -83,23 +83,17 @@ abstract class TaskQueue implements ITaskQueue {
if (!this._tasks[this._i]()) {
this._i++;
}
/*
* other than performance.now, performance.now might not be stable (changes on wall clock
* changes), this is not an issue here as a clock change during a short running task is very
* unlikely in case it still happened and leads to negative duration, simply assume 1 msec
*/
// other than performance.now, performance.now might not be stable (changes on wall clock
// changes), this is not an issue here as a clock change during a short running task is very
// unlikely in case it still happened and leads to negative duration, simply assume 1 msec
taskDuration = Math.max(1, performance.now() - taskDuration);
longestTask = Math.max(taskDuration, longestTask);
/*
* Guess the following task will take a similar time to the longest task in this batch, allow
* additional room to try avoid exceeding the deadline
*/
// Guess the following task will take a similar time to the longest task in this batch, allow
// additional room to try avoid exceeding the deadline
deadlineRemaining = deadline.timeRemaining();
if (longestTask * 1.5 > deadlineRemaining) {
/*
* Warn when the time exceeding the deadline is over 20ms, if this happens in practice the
* task should be split into sub-tasks to ensure the UI remains responsive.
*/
// Warn when the time exceeding the deadline is over 20ms, if this happens in practice the
// task should be split into sub-tasks to ensure the UI remains responsive.
if (lastDeadlineRemaining - taskDuration < -20) {
this._logService.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(lastDeadlineRemaining - taskDuration))}ms`);
}
+14 -16
View File
@@ -310,10 +310,8 @@ export const enum CoreMouseButton {
RIGHT = 2,
NONE = 3,
WHEEL = 4,
/*
* additional buttons 1..8
* untested!
*/
// additional buttons 1..8
// untested!
AUX1 = 8,
AUX2 = 9,
AUX3 = 10,
@@ -532,7 +530,7 @@ export interface IInputHandler {
/**
* OSC 0
* OSC 2
* OSC 2
*/ setTitle(data: string): boolean;
/** OSC 4 */ setOrReportIndexedColor(data: string): boolean;
/** OSC 10 */ setOrReportFgColor(data: string): boolean;
@@ -548,16 +546,16 @@ export interface IInputHandler {
/** ESC > */ keypadNumericMode(): boolean;
/**
* ESC % G
* ESC % @
* ESC % @
*/ selectDefaultCharset(): boolean;
/**
* ESC ( C
* ESC ) C
* ESC * C
* ESC + C
* ESC - C
* ESC . C
* ESC / C
* ESC ) C
* ESC * C
* ESC + C
* ESC - C
* ESC . C
* ESC / C
*/ selectCharset(collectAndFlag: string): boolean;
/** ESC D */ index(): boolean;
/** ESC H */ tabSet(): boolean;
@@ -565,10 +563,10 @@ export interface IInputHandler {
/** ESC c */ fullReset(): boolean;
/**
* ESC n
* ESC o
* ESC |
* ESC }
* ESC ~
* ESC o
* ESC |
* ESC }
* ESC ~
*/ setgLevel(level: number): boolean;
/** ESC # 8 */ screenAlignmentPattern(): boolean;
}
+10 -12
View File
@@ -7,18 +7,16 @@ import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from 'comm
import { IBufferService } from 'common/services/Services';
export function updateWindowsModeWrappedState(bufferService: IBufferService): void {
/*
* Winpty does not support wraparound mode which means that lines will never
* be marked as wrapped. This causes issues for things like copying a line
* retaining the wrapped new line characters or if consumers are listening
* in on the data stream.
*
* The workaround for this is to listen to every incoming line feed and mark
* the line as wrapped if the last character in the previous line is not a
* space. This is certainly not without its problems, but generally on
* Windows when text reaches the end of the terminal it's likely going to be
* wrapped.
*/
// Winpty does not support wraparound mode which means that lines will never
// be marked as wrapped. This causes issues for things like copying a line
// retaining the wrapped new line characters or if consumers are listening
// in on the data stream.
//
// The workaround for this is to listen to every incoming line feed and mark
// the line as wrapped if the last character in the previous line is not a
// space. This is certainly not without its problems, but generally on
// Windows when text reaches the end of the terminal it's likely going to be
// wrapped.
const line = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y - 1);
const lastChar = line?.get(bufferService.cols - 1);
+46 -66
View File
@@ -348,10 +348,8 @@ describe('Buffer', () => {
assert.equal(buffer.lines.get(4)!.translateToString(), ' ');
});
it('should remove the correct amount of rows when reflowing larger', () => {
/*
* This is a regression test to ensure that successive wrapped lines that are getting
* 3+ lines removed on a reflow actually remove the right lines
*/
// This is a regression test to ensure that successive wrapped lines that are getting
// 3+ lines removed on a reflow actually remove the right lines
buffer.fillViewportRows();
buffer.resize(10, 10);
buffer.y = 2;
@@ -431,12 +429,10 @@ describe('Buffer', () => {
buffer.lines.get(2)!.set(i, [0, char, 1, code]);
}
buffer.y = 3;
/*
* Buffer:
* abcdefghij
* 0123456789
* abcdefghij
*/
// Buffer:
// abcdefghij
// 0123456789
// abcdefghij
const firstMarker = buffer.addMarker(0);
const secondMarker = buffer.addMarker(1);
const thirdMarker = buffer.addMarker(2);
@@ -496,12 +492,10 @@ describe('Buffer', () => {
buffer.lines.get(2)!.set(i, [0, char, 1, code]);
}
buffer.y = 10;
/*
* Buffer:
* abcdefghij
* 0123456789
* abcdefghij
*/
// Buffer:
// abcdefghij
// 0123456789
// abcdefghij
const firstMarker = buffer.addMarker(0);
const secondMarker = buffer.addMarker(1);
const thirdMarker = buffer.addMarker(2);
@@ -545,11 +539,9 @@ describe('Buffer', () => {
buffer.lines.get(1)!.set(0, [0, 'c', 1, 'c'.charCodeAt(0)]);
buffer.lines.get(1)!.set(1, [0, 'd', 1, 'd'.charCodeAt(0)]);
buffer.lines.get(1)!.isWrapped = true;
/*
* Buffer:
* "ab " (wrapped)
* "cd"
*/
// Buffer:
// "ab " (wrapped)
// "cd"
buffer.resize(5, 10);
assert.equal(buffer.ybase, 0);
assert.equal(buffer.lines.length, 10);
@@ -578,11 +570,9 @@ describe('Buffer', () => {
buffer.lines.get(1)!.set(i, [0, '', 0, 0]);
}
buffer.lines.get(1)!.isWrapped = true;
/*
* Buffer:
* 汉语汉语汉语 (wrapped)
* 汉语汉语汉语
*/
// Buffer:
// 汉语汉语汉语 (wrapped)
// 汉语汉语汉语
assert.equal(buffer.lines.get(0)!.translateToString(true), '汉语汉语汉语');
assert.equal(buffer.lines.get(1)!.translateToString(true), '汉语汉语汉语');
buffer.resize(13, 10);
@@ -607,11 +597,9 @@ describe('Buffer', () => {
buffer.lines.get(1)!.set(0, [0, 'c', 1, 'c'.charCodeAt(0)]);
buffer.lines.get(1)!.set(1, [0, 'd', 1, 'd'.charCodeAt(0)]);
buffer.lines.get(1)!.isWrapped = true;
/*
* Buffer:
* "ab " (wrapped)
* "cd"
*/
// Buffer:
// "ab " (wrapped)
// "cd"
buffer.resize(3, 10);
assert.equal(buffer.y, 2);
assert.equal(buffer.ybase, 0);
@@ -643,11 +631,9 @@ describe('Buffer', () => {
buffer.lines.get(1)!.set(i, [0, '', 0, 0]);
}
buffer.lines.get(1)!.isWrapped = true;
/*
* Buffer:
* 汉语汉语汉语 (wrapped)
* 汉语汉语汉语
*/
// Buffer:
// 汉语汉语汉语 (wrapped)
// 汉语汉语汉语
assert.equal(buffer.lines.get(0)!.translateToString(true), '汉语汉语汉语');
assert.equal(buffer.lines.get(1)!.translateToString(true), '汉语汉语汉语');
buffer.resize(11, 10);
@@ -682,19 +668,17 @@ describe('Buffer', () => {
describe('reflowLarger cases', () => {
beforeEach(() => {
/*
* Setup buffer state:
* 'ab'
* 'cd' (wrapped)
* 'ef'
* 'gh' (wrapped)
* 'ij'
* 'kl' (wrapped)
* ' '
* ' '
* ' '
* ' '
*/
// Setup buffer state:
// 'ab'
// 'cd' (wrapped)
// 'ef'
// 'gh' (wrapped)
// 'ij'
// 'kl' (wrapped)
// ' '
// ' '
// ' '
// ' '
buffer.fillViewportRows();
buffer.resize(2, 10);
buffer.lines.get(0)!.set(0, [0, 'a', 1, 'a'.charCodeAt(0)]);
@@ -875,19 +859,17 @@ describe('Buffer', () => {
});
describe('reflowSmaller cases', () => {
beforeEach(() => {
/*
* Setup buffer state:
* 'abcd'
* 'efgh' (wrapped)
* 'ijkl'
* ' '
* ' '
* ' '
* ' '
* ' '
* ' '
* ' '
*/
// Setup buffer state:
// 'abcd'
// 'efgh' (wrapped)
// 'ijkl'
// ' '
// ' '
// ' '
// ' '
// ' '
// ' '
// ' '
buffer.fillViewportRows();
buffer.resize(4, 10);
buffer.lines.get(0)!.set(0, [0, 'a', 1, 'a'.charCodeAt(0)]);
@@ -1319,10 +1301,8 @@ describe('Buffer', () => {
assert.equal(line.length, INIT_COLS / 2 - 1);
}
/*
* wait for a bit to give IdleTaskQueue a chance to kick in
* and finish memory cleaning
*/
// wait for a bit to give IdleTaskQueue a chance to kick in
// and finish memory cleaning
await new Promise(r => setTimeout(r, 30));
// cleanup should have realigned memory with exact bytelength
+35 -67
View File
@@ -169,25 +169,19 @@ export class Buffer extends Disposable implements IBuffer {
// count bufferlines with overly big memory to be cleaned afterwards
let dirtyMemoryLines = 0;
/*
* Increase max length if needed before adjustments to allow space to fill
* as required.
*/
// Increase max length if needed before adjustments to allow space to fill
// as required.
const newMaxLength = this._getCorrectBufferLength(newRows);
if (newMaxLength > this.lines.maxLength) {
this.lines.maxLength = newMaxLength;
}
/*
* if (this._cols > newCols) {
* console.log('increase!');
* }
*/
// if (this._cols > newCols) {
// console.log('increase!');
// }
/*
* The following adjustments should only happen if the buffer has been
* initialized/filled.
*/
// The following adjustments should only happen if the buffer has been
// initialized/filled.
if (this.lines.length > 0) {
// Deal with columns increasing (reducing needs to happen after reflow)
if (this._cols < newCols) {
@@ -203,17 +197,13 @@ export class Buffer extends Disposable implements IBuffer {
for (let y = this._rows; y < newRows; y++) {
if (this.lines.length < newRows + this.ybase) {
if (this._optionsService.rawOptions.windowsPty.backend !== undefined || this._optionsService.rawOptions.windowsPty.buildNumber !== undefined) {
/*
* Just add the new missing rows on Windows as conpty reprints the screen with it's
* view of the world. Once a line enters scrollback for conpty it remains there
*/
// Just add the new missing rows on Windows as conpty reprints the screen with it's
// view of the world. Once a line enters scrollback for conpty it remains there
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
} else {
if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
/*
* There is room above the buffer and there are no empty elements below the line,
* scroll up
*/
// There is room above the buffer and there are no empty elements below the line,
// scroll up
this.ybase--;
addToY++;
if (this.ydisp > 0) {
@@ -221,10 +211,8 @@ export class Buffer extends Disposable implements IBuffer {
this.ydisp--;
}
} else {
/*
* Add a blank line if there is no buffer left at the top to scroll to, or if there
* are blank lines after the cursor
*/
// Add a blank line if there is no buffer left at the top to scroll to, or if there
// are blank lines after the cursor
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
}
}
@@ -245,10 +233,8 @@ export class Buffer extends Disposable implements IBuffer {
}
}
/*
* Reduce max length if needed after adjustments, this is done after as it
* would otherwise cut data from the bottom of the buffer.
*/
// Reduce max length if needed after adjustments, this is done after as it
// would otherwise cut data from the bottom of the buffer.
if (newMaxLength < this.lines.maxLength) {
// Trim from the top of the buffer and adjust ybase and ydisp.
const amountToTrim = this.lines.length - newMaxLength;
@@ -289,10 +275,8 @@ export class Buffer extends Disposable implements IBuffer {
this._cols = newCols;
this._rows = newRows;
/*
* Ensure the cursor position invariant: ybase + y must be within buffer bounds
* This can be violated during reflow or when shrinking rows
*/
// Ensure the cursor position invariant: ybase + y must be within buffer bounds
// This can be violated during reflow or when shrinking rows
if (this.lines.length > 0) {
const maxY = Math.max(0, this.lines.length - this.ybase - 1);
this.y = Math.min(this.y, maxY);
@@ -309,10 +293,8 @@ export class Buffer extends Disposable implements IBuffer {
private _batchedMemoryCleanup(): boolean {
let normalRun = true;
if (this._memoryCleanupPosition >= this.lines.length) {
/*
* cleanup made it once through all lines, thus rescan in loop below to also catch shifted
* lines, which should finish rather quick if there are no more cleanups pending
*/
// cleanup made it once through all lines, thus rescan in loop below to also catch shifted
// lines, which should finish rather quick if there are no more cleanups pending
this._memoryCleanupPosition = 0;
normalRun = false;
}
@@ -324,11 +306,9 @@ export class Buffer extends Disposable implements IBuffer {
return true;
}
}
/*
* normal runs always need another rescan afterwards
* if we made it here with normalRun=false, we are in a final run
* and can end the cleanup task for sure
*/
// normal runs always need another rescan afterwards
// if we made it here with normalRun=false, we are in a final run
// and can end the cleanup task for sure
return normalRun;
}
@@ -389,10 +369,8 @@ export class Buffer extends Disposable implements IBuffer {
private _reflowSmaller(newCols: number, newRows: number): void {
const reflowCursorLine = this._optionsService.rawOptions.reflowCursorLine;
const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);
/*
* Gather all BufferLines that need to be inserted into the Buffer here so that they can be
* batched up and only committed once
*/
// Gather all BufferLines that need to be inserted into the Buffer here so that they can be
// batched up and only committed once
const toInsert = [];
let countToInsert = 0;
// Go backwards as many lines may be trimmed and this will avoid considering them
@@ -411,10 +389,8 @@ export class Buffer extends Disposable implements IBuffer {
}
if (!reflowCursorLine) {
/*
* If these lines contain the cursor don't touch them, the program will handle fixing up
* wrapped lines with the cursor
*/
// If these lines contain the cursor don't touch them, the program will handle fixing up
// wrapped lines with the cursor
const absoluteY = this.ybase + this.y;
if (absoluteY >= y && absoluteY < y + wrappedLines.length) {
continue;
@@ -440,10 +416,8 @@ export class Buffer extends Disposable implements IBuffer {
}
if (newLines.length > 0) {
toInsert.push({
/*
* countToInsert here gets the actual index, taking into account other inserted items.
* using this we can iterate through the list forwards
*/
// countToInsert here gets the actual index, taking into account other inserted items.
// using this we can iterate through the list forwards
start: y + wrappedLines.length + countToInsert,
newLines
});
@@ -463,10 +437,8 @@ export class Buffer extends Disposable implements IBuffer {
while (srcLineIndex >= 0) {
const cellsToCopy = Math.min(srcCol, destCol);
if (wrappedLines[destLineIndex] === undefined) {
/*
* Sanity check that the line exists, this has been known to fail for an unknown reason
* which would stop the reflow from happening if an exception would throw.
*/
// Sanity check that the line exists, this has been known to fail for an unknown reason
// which would stop the reflow from happening if an exception would throw.
break;
}
wrappedLines[destLineIndex].copyCellsFrom(wrappedLines[srcLineIndex], srcCol - cellsToCopy, destCol - cellsToCopy, cellsToCopy, true);
@@ -514,16 +486,12 @@ export class Buffer extends Disposable implements IBuffer {
this.savedY = Math.min(this.savedY + linesToAdd, this.ybase + newRows - 1);
}
/*
* Rearrange lines in the buffer if there are any insertions, this is done at the end rather
* than earlier so that it's a single O(n) pass through the buffer, instead of O(n^2) from many
* costly calls to CircularList.splice.
*/
// Rearrange lines in the buffer if there are any insertions, this is done at the end rather
// than earlier so that it's a single O(n) pass through the buffer, instead of O(n^2) from many
// costly calls to CircularList.splice.
if (toInsert.length > 0) {
/*
* Record buffer insert events and then play them back backwards so that the indexes are
* correct
*/
// Record buffer insert events and then play them back backwards so that the indexes are
// correct
const insertEvents: IInsertEvent[] = [];
// Record original lines so they don't get overridden when we rearrange the list
+12 -22
View File
@@ -288,11 +288,9 @@ describe('BufferLine', function(): void {
assert.equal(line2.isWrapped, line.isWrapped);
});
it('should support combining chars', function(): void {
/*
* CHAR_DATA_CODE_INDEX resembles current behavior in InputHandler.print
* --> set code to the last charCodeAt value of the string
* Note: needs to be fixed once the string pointer is in place
*/
// CHAR_DATA_CODE_INDEX resembles current behavior in InputHandler.print
// --> set code to the last charCodeAt value of the string
// Note: needs to be fixed once the string pointer is in place
const line = new TestBufferLine(2, createCellData(1, 'e\u0301', 1));
assert.deepEqual(line.toArray(), [[1, 'e\u0301', 1, '\u0301'.charCodeAt(0)], [1, 'e\u0301', 1, '\u0301'.charCodeAt(0)]]);
const line2 = new TestBufferLine(5, createCellData(1, 'a', 1), true);
@@ -480,11 +478,9 @@ describe('BufferLine', function(): void {
});
it('should always return some sane value', function(): void {
const columns: number[] = [];
/*
* sanity check - broken line with invalid out of bound null width cells
* this can atm happen with deleting/inserting chars in inputhandler by "breaking"
* fullwidth pairs --> needs to be fixed after settling BufferLine impl
*/
// sanity check - broken line with invalid out of bound null width cells
// this can atm happen with deleting/inserting chars in inputhandler by "breaking"
// fullwidth pairs --> needs to be fixed after settling BufferLine impl
const line = new TestBufferLine(10, NULL_CELL_DATA, false);
assert.equal(line.translateToString(false, undefined, undefined, columns), ' ');
assert.deepEqual(columns, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
@@ -504,10 +500,8 @@ describe('BufferLine', function(): void {
const line = new TestBufferLine(3, NULL_CELL_DATA, false);
line.addCodepointToCell(0, '\u0301'.charCodeAt(0), 0);
const cell = line.loadCell(0, new CellData());
/*
* chars contains single combining char
* width is set to 1
*/
// chars contains single combining char
// width is set to 1
assert.deepEqual(cell.getAsCharData(), [DEFAULT_ATTR, '\u0301', 1, 0x0301]);
// do not account a single combining char as combined
assert.equal(cell.isCombined(), 0);
@@ -519,10 +513,8 @@ describe('BufferLine', function(): void {
line.setCell(0, cell);
line.addCodepointToCell(0, '\u0301'.charCodeAt(0), 0);
line.loadCell(0, cell);
/*
* chars contains 3 chars
* width is set to 1
*/
// chars contains 3 chars
// width is set to 1
assert.deepEqual(cell.getAsCharData(), [123, 'e\u0301\u0301', 1, 0x0301]);
// do not account a single combining char as combined
assert.equal(cell.isCombined(), Content.IS_COMBINED_MASK);
@@ -534,10 +526,8 @@ describe('BufferLine', function(): void {
line.setCell(0, cell);
line.addCodepointToCell(0, '\u0301'.charCodeAt(0), 0);
line.loadCell(0, cell);
/*
* chars contains 2 chars
* width is set to 1
*/
// chars contains 2 chars
// width is set to 1
assert.deepEqual(cell.getAsCharData(), [123, 'e\u0301', 1, 0x0301]);
// do not account a single combining char as combined
assert.equal(cell.isCombined(), Content.IS_COMBINED_MASK);
+13 -21
View File
@@ -9,13 +9,11 @@ import { CellData } from 'common/buffer/CellData';
import { Attributes, BgFlags, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, Content, NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
import { stringFromCodePoint } from 'common/input/TextDecoder';
/*
* Buffer memory layout:
*
* [0]: content `uint32_t` - wcwidth(2) comb(1) codepoint(21)
* [1]: fg `uint32_t` - flags(8) r(8) g(8) b(8)
* [2]: bg `uint32_t` - flags(8) r(8) g(8) b(8)
*/
// Buffer memory layout:
//
// [0]: content `uint32_t` - wcwidth(2) comb(1) codepoint(21)
// [1]: fg `uint32_t` - flags(8) r(8) g(8) b(8)
// [2]: bg `uint32_t` - flags(8) r(8) g(8) b(8)
const enum Constants {
/** The number of 32 bit array indices taken by one cell. */
@@ -257,19 +255,15 @@ export class BufferLine implements IBufferLine {
this._combined[index] += stringFromCodePoint(codePoint);
} else {
if (content & Content.CODEPOINT_MASK) {
/*
* normal case for combining chars:
* - move current leading char + new one into combined string
* - set combined flag
*/
// normal case for combining chars:
// - move current leading char + new one into combined string
// - set combined flag
this._combined[index] = stringFromCodePoint(content & Content.CODEPOINT_MASK) + stringFromCodePoint(codePoint);
content &= ~Content.CODEPOINT_MASK; // set codepoint in buffer to 0
content |= Content.IS_COMBINED_MASK;
} else {
/*
* should not happen - we actually have no data in the cell yet
* simply set the data in the cell buffer with a width of 1
*/
// should not happen - we actually have no data in the cell yet
// simply set the data in the cell buffer with a width of 1
content = codePoint | (1 << Content.WIDTH_SHIFT);
}
}
@@ -324,11 +318,9 @@ export class BufferLine implements IBufferLine {
}
}
/*
* handle fullwidth at pos:
* - reset pos-1 if wide char
* - reset pos if width==0 (previous second cell of a wide char)
*/
// handle fullwidth at pos:
// - reset pos-1 if wide char
// - reset pos if width==0 (previous second cell of a wide char)
if (pos && this.getWidth(pos - 1) === 2) {
this.setCellFromCodepoint(pos - 1, 0, 1, fillCellData);
}
+9 -17
View File
@@ -23,10 +23,8 @@ export interface INewLayoutResult {
* @param reflowCursorLine Whether to reflow the line containing the cursor.
*/
export function reflowLargerGetLinesToRemove(lines: CircularList<IBufferLine>, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData, reflowCursorLine: boolean): number[] {
/*
* Gather all BufferLines that need to be removed from the Buffer here so that they can be
* batched up and only committed once
*/
// Gather all BufferLines that need to be removed from the Buffer here so that they can be
// batched up and only committed once
const toRemove: number[] = [];
for (let y = 0; y < lines.length - 1; y++) {
@@ -45,10 +43,8 @@ export function reflowLargerGetLinesToRemove(lines: CircularList<IBufferLine>, o
}
if (!reflowCursorLine) {
/*
* If these lines contain the cursor don't touch them, the program will handle fixing up
* wrapped lines with the cursor
*/
// If these lines contain the cursor don't touch them, the program will handle fixing up
// wrapped lines with the cursor
if (bufferAbsoluteY >= y && bufferAbsoluteY < i) {
y += wrappedLines.length - 1;
continue;
@@ -184,10 +180,8 @@ export function reflowSmallerGetNewLineLengths(wrappedLines: BufferLine[], oldCo
const newLineLengths: number[] = [];
const cellsNeeded = wrappedLines.map((l, i) => getWrappedLineTrimmedLength(wrappedLines, i, oldCols)).reduce((p, c) => p + c);
/*
* Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and
* linesNeeded
*/
// Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and
// linesNeeded
let srcCol = 0;
let srcLine = 0;
let cellsAvailable = 0;
@@ -220,11 +214,9 @@ export function getWrappedLineTrimmedLength(lines: BufferLine[], i: number, cols
if (i === lines.length - 1) {
return lines[i].getTrimmedLength();
}
/*
* Detect whether the following line starts with a wide character and the end of the current line
* is null, if so then we can be pretty sure the null character should be excluded from the line
* length]
*/
// Detect whether the following line starts with a wide character and the end of the current line
// is null, if so then we can be pretty sure the null character should be excluded from the line
// length]
const endsInNull = !(lines[i].hasContent(cols - 1)) && lines[i].getWidth(cols - 1) === 1;
const followingLineStartsWithWide = lines[i + 1].getWidth(0) === 2;
if (endsInNull && followingLineStartsWithWide) {
+7 -13
View File
@@ -43,10 +43,8 @@ export class BufferSet extends Disposable implements IBufferSet {
this._normalBuffer.value = this._normal;
this._normal.fillViewportRows();
/*
* The alt buffer should never have scrollback.
* See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
*/
// The alt buffer should never have scrollback.
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
this._alt = new Buffer(false, this._optionsService, this._bufferService, this._logService);
this._altBuffer.value = this._alt;
this._activeBuffer = this._normal;
@@ -88,11 +86,9 @@ export class BufferSet extends Disposable implements IBufferSet {
}
this._normal.x = this._alt.x;
this._normal.y = this._alt.y;
/*
* 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.
*/
// 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.clearAllMarkers();
this._alt.clear();
this._activeBuffer = this._normal;
@@ -109,10 +105,8 @@ export class BufferSet extends Disposable implements IBufferSet {
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.
*/
// 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(fillAttr);
this._alt.x = this._normal.x;
this._alt.y = this._normal.y;
+2 -4
View File
@@ -65,10 +65,8 @@ export class CellData extends AttributeData implements ICellData {
}
else if (value[CHAR_DATA_CHAR_INDEX].length === 2) {
const code = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0);
/*
* if the 2-char string is a surrogate create single codepoint
* everything else is combined
*/
// if the 2-char string is a surrogate create single codepoint
// everything else is combined
if (0xD800 <= code && code <= 0xDBFF) {
const second = value[CHAR_DATA_CHAR_INDEX].charCodeAt(1);
if (0xDC00 <= second && second <= 0xDFFF) {
+2 -4
View File
@@ -123,10 +123,8 @@ describe('Keyboard', () => {
});
describe('On non-macOS platforms', () => {
/*
* Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100
* http://unix.stackexchange.com/a/108106
*/
// Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100
// http://unix.stackexchange.com/a/108106
it('should return \\x1b[1;3D for alt+left', () => {
assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 37 }, { isMac: false }).key, '\x1b[1;3D'); // CSI 1;3 D
});
+13 -23
View File
@@ -43,10 +43,8 @@ export function evaluateKeyboardEvent(
): IKeyboardResult {
const result: IKeyboardResult = {
type: KeyboardResultType.SEND_KEY,
/*
* Whether to cancel event propagation (NOTE: this may not be needed since the event is
* canceled at the end of keyDown
*/
// Whether to cancel event propagation (NOTE: this may not be needed since the event is
// canceled at the end of keyDown
cancel: false,
// The new key even to emit
key: undefined
@@ -102,10 +100,8 @@ export function evaluateKeyboardEvent(
case 13:
// return/enter
if (ev.key === 'c' && ev.ctrlKey) {
/*
* HACK: Safari on iPad, iOS, AppleVisionPro sends key 13 when typing ctrl-c on hardware
* keyboard
*/
// HACK: Safari on iPad, iOS, AppleVisionPro sends key 13 when typing ctrl-c on hardware
// keyboard
result.key = C0.ETX;
} else {
result.key = ev.altKey ? C0.ESC + C0.CR : C0.CR;
@@ -175,10 +171,8 @@ export function evaluateKeyboardEvent(
case 45:
// insert
if (!ev.shiftKey && !ev.ctrlKey) {
/*
* <Ctrl> or <Shift> + <Insert> are used to
* copy-paste on some systems.
*/
// <Ctrl> or <Shift> + <Insert> are used to
// copy-paste on some systems.
result.key = C0.ESC + '[2~';
}
break;
@@ -352,13 +346,11 @@ export function evaluateKeyboardEvent(
} else if (ev.keyCode === 32) {
result.key = C0.ESC + (ev.ctrlKey ? C0.NUL : ' ');
} else if (ev.key === 'Dead' && ev.code.startsWith('Key')) {
/*
* Reference: https://github.com/xtermjs/xterm.js/issues/3725
* Alt will produce a "dead key" (initate composition) with some
* of the letters in US layout (e.g. N/E/U).
* It's safe to match against Key* since no other `code` values begin with "Key".
* https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values#code_values_on_mac
*/
// Reference: https://github.com/xtermjs/xterm.js/issues/3725
// Alt will produce a "dead key" (initate composition) with some
// of the letters in US layout (e.g. N/E/U).
// It's safe to match against Key* since no other `code` values begin with "Key".
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values#code_values_on_mac
let keyString = ev.code.slice(3, 4);
if (!ev.shiftKey) {
keyString = keyString.toLowerCase();
@@ -371,10 +363,8 @@ export function evaluateKeyboardEvent(
result.type = KeyboardResultType.SELECT_ALL;
}
} else if (ev.key && !ev.ctrlKey && !ev.altKey && !ev.metaKey && ev.keyCode >= 48 && ev.key.length === 1) {
/*
* Include only keys that that result in a _single_ character; don't include num lock,
* volume up, etc.
*/
// Include only keys that that result in a _single_ character; don't include num lock,
// volume up, etc.
result.key = ev.key;
} else if (ev.key && ev.ctrlKey && ev.shiftKey) {
switch (ev.code) {
+4 -8
View File
@@ -40,10 +40,8 @@ describe('KittyKeyboard', () => {
const flags = KittyKeyboardFlags.DISAMBIGUATE_ESCAPE_CODES;
it('shift+letter sends plain character in DISAMBIGUATE mode', () => {
/*
* Kitty spec: DISAMBIGUATE only encodes keys ambiguous in legacy encoding
* Shift+a → "A" is not ambiguous, so send plain "A"
*/
// Kitty spec: DISAMBIGUATE only encodes keys ambiguous in legacy encoding
// Shift+a → "A" is not ambiguous, so send plain "A"
const result = kitty.evaluate(createEvent({ key: 'A', shiftKey: true }), flags);
assert.strictEqual(result.key, 'A');
});
@@ -556,10 +554,8 @@ describe('KittyKeyboard', () => {
});
});
/*
* Enabling REPORT_EVENT_TYPES without DISAMBIGUATE_ESCAPE_CODES doesn't really make sense and
* isn't specified in the spec, but press and repeat events shouldn't get swallowed.
*/
// Enabling REPORT_EVENT_TYPES without DISAMBIGUATE_ESCAPE_CODES doesn't really make sense and
// isn't specified in the spec, but press and repeat events shouldn't get swallowed.
describe('REPORT_EVENT_TYPES flag without DISAMBIGUATE_ESCAPE_CODES', () => {
const flags = KittyKeyboardFlags.REPORT_EVENT_TYPES;
+12 -20
View File
@@ -437,12 +437,10 @@ export class KittyKeyboard {
return result;
}
/*
* Spec § "Report all keys as escape codes": "Additionally, with this mode,
* events for pressing modifier keys are reported." — i.e. *without* this
* mode, modifier-key press events are suppressed. Kitty's is_modifier_key()
* treats CapsLock/NumLock/ScrollLock as modifier keys for this rule.
*/
// Spec § "Report all keys as escape codes": "Additionally, with this mode,
// events for pressing modifier keys are reported." — i.e. *without* this
// mode, modifier-key press events are suppressed. Kitty's is_modifier_key()
// treats CapsLock/NumLock/ScrollLock as modifier keys for this rule.
if (this._isLockKey(ev) && !(flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES)) {
return result;
}
@@ -476,10 +474,8 @@ export class KittyKeyboard {
// Special handling for Enter/Tab/Backspace.
const specialKey = keyCode === 13 || keyCode === 9 || keyCode === 127;
/*
* Per spec, Enter/Tab/Backspace will not have release events unless "Report all keys as escape
* codes" is also set.
*/
// Per spec, Enter/Tab/Backspace will not have release events unless "Report all keys as escape
// codes" is also set.
if (specialKey && eventType === KittyKeyboardEventType.RELEASE && !(flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES)) {
return result;
}
@@ -489,18 +485,14 @@ export class KittyKeyboard {
const useCsiU = !!(
flags & KittyKeyboardFlags.REPORT_ALL_KEYS_AS_ESCAPE_CODES ||
(reportEventTypes && eventType === KittyKeyboardEventType.RELEASE) ||
/*
* Enabling REPORT_EVENT_TYPES without DISAMBIGUATE_ESCAPE_CODES doesn't really make sense, so
* just make REPORT_EVENT_TYPES imply DISAMBIGUATE_ESCAPE_CODES here for simplicity.
* See: https://github.com/kovidgoyal/kitty/issues/9999
*/
// Enabling REPORT_EVENT_TYPES without DISAMBIGUATE_ESCAPE_CODES doesn't really make sense, so
// just make REPORT_EVENT_TYPES imply DISAMBIGUATE_ESCAPE_CODES here for simplicity.
// See: https://github.com/kovidgoyal/kitty/issues/9999
((flags & KittyKeyboardFlags.DISAMBIGUATE_ESCAPE_CODES || reportEventTypes) &&
(
/*
* Per spec, Enter/Tab/Backspace "still generate the same bytes as in legacy mode" and
* consider space to be a text-generating key, so these skip the isFunc fast-path and only
* get CSI u when modifiers are present (handled below).
*/
// Per spec, Enter/Tab/Backspace "still generate the same bytes as in legacy mode" and
// consider space to be a text-generating key, so these skip the isFunc fast-path and only
// get CSI u when modifiers are present (handled below).
(isFunc && !specialKey) ||
(
(modifiers > 0 && ev.key.length !== 1) ||
+5 -7
View File
@@ -28,13 +28,11 @@ export function utf32ToString(data: Uint32Array, start: number = 0, end: number
for (let i = start; i < end; ++i) {
let codepoint = data[i];
if (codepoint > 0xFFFF) {
/*
* JS strings are encoded as UTF16, thus a non BMP codepoint gets converted into a surrogate
* pair conversion rules:
* - subtract 0x10000 from code point, leaving a 20 bit number
* - add high 10 bits to 0xD800 --> first surrogate
* - add low 10 bits to 0xDC00 --> second surrogate
*/
// JS strings are encoded as UTF16, thus a non BMP codepoint gets converted into a surrogate
// pair conversion rules:
// - subtract 0x10000 from code point, leaving a 20 bit number
// - add high 10 bits to 0xD800 --> first surrogate
// - add low 10 bits to 0xDC00 --> second surrogate
codepoint -= 0x10000;
result += String.fromCharCode((codepoint >> 10) + 0xD800) + String.fromCharCode((codepoint % 0x400) + 0xDC00);
} else {
+14 -18
View File
@@ -12,10 +12,8 @@ it('wcwidth should match all values from the old implementation', function(): vo
// old implementation
const wcwidthOld = (function(opts: {nul: number, control: number}): (ucs: number) => number {
/*
* extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
* combining characters
*/
// extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
// combining characters
const COMBINING_BMP = [
[0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
[0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],
@@ -151,20 +149,18 @@ it('wcwidth should match all values from the old implementation', function(): vo
}
return table;
}
/*
* get width from lookup table
* position in container : num / CODEPOINTS_PER_ITEM
* ==> n = table[Math.floor(num / 16)]
* ==> n = table[num >> 4]
* 16 codepoints per number: FFEEDDCCBBAA99887766554433221100
* position in number : (num % CODEPOINTS_PER_ITEM) * BITWIDTH
* ==> m = (n % 16) * 2
* ==> m = (num & 15) << 1
* right shift to position m
* ==> n = n >> m e.g. m=12 000000000000FFEEDDCCBBAA99887766
* we are only interested in 2 LSBs, cut off higher bits
* ==> n = n & 3 e.g. 000000000000000000000000000000XX
*/
// get width from lookup table
// position in container : num / CODEPOINTS_PER_ITEM
// ==> n = table[Math.floor(num / 16)]
// ==> n = table[num >> 4]
// 16 codepoints per number: FFEEDDCCBBAA99887766554433221100
// position in number : (num % CODEPOINTS_PER_ITEM) * BITWIDTH
// ==> m = (n % 16) * 2
// ==> m = (num & 15) << 1
// right shift to position m
// ==> n = n >> m e.g. m=12 000000000000FFEEDDCCBBAA99887766
// we are only interested in 2 LSBs, cut off higher bits
// ==> n = n & 3 e.g. 000000000000000000000000000000XX
return (num: number): number => {
num |= 0; // get asm.js like optimization under V8
if (num < 32) {
+7 -11
View File
@@ -94,10 +94,8 @@ export class UnicodeV6 implements IUnicodeVersionProvider {
table.fill(0, 1, 32);
table.fill(0, 0x7f, 0xa0);
/*
* apply wide char rules first
* wide chars
*/
// apply wide char rules first
// wide chars
table.fill(2, 0x1100, 0x1160);
table[0x2329] = 2;
table[0x232a] = 2;
@@ -111,13 +109,11 @@ export class UnicodeV6 implements IUnicodeVersionProvider {
table.fill(2, 0xff00, 0xff61);
table.fill(2, 0xffe0, 0xffe7);
/*
* apply combining last to ensure we overwrite
* wrongly wide set chars:
* the original algo evals combining first and falls
* through to wide check so we simply do here the opposite
* combining 0
*/
// apply combining last to ensure we overwrite
// wrongly wide set chars:
// the original algo evals combining first and falls
// through to wide check so we simply do here the opposite
// combining 0
for (let r = 0; r < BMP_COMBINING.length; ++r) {
table.fill(0, BMP_COMBINING[r][0], BMP_COMBINING[r][1] + 1);
}
+5 -9
View File
@@ -198,10 +198,8 @@ export class Win32InputMode {
* Returns 0 for non-character keys.
*/
private _getUnicodeChar(ev: IKeyboardEvent): number {
/*
* Handle special keys that produce control characters
* Ctrl modifies some of these: Ctrl+Enter=LF, Ctrl+Backspace=DEL
*/
// Handle special keys that produce control characters
// Ctrl modifies some of these: Ctrl+Enter=LF, Ctrl+Backspace=DEL
if (ev.ctrlKey && !ev.altKey && !ev.metaKey) {
if (ev.key === 'Enter') {
return 0x0A; // Line feed (Ctrl+Enter)
@@ -247,11 +245,9 @@ export class Win32InputMode {
state |= Win32ControlKeyState.SHIFT_PRESSED;
}
/*
* Note: We can't distinguish left/right for ctrl/alt in standard browser events,
* so we use the generic pressed flags. The right-side flags are used when
* we can detect them (e.g., via code property).
*/
// Note: We can't distinguish left/right for ctrl/alt in standard browser events,
// so we use the generic pressed flags. The right-side flags are used when
// we can detect them (e.g., via code property).
if (ev.ctrlKey) {
if (ev.code === 'ControlRight') {
state |= Win32ControlKeyState.RIGHT_CTRL_PRESSED;
+24 -40
View File
@@ -90,16 +90,12 @@ export class WriteBuffer extends Disposable {
* @deprecated Unreliable, to be removed soon.
*/
public writeSync(data: string | Uint8Array, maxSubsequentCalls?: number): void {
/*
* stop writeSync recursions with maxSubsequentCalls argument
* This is dangerous to use as it will lose the current data chunk
* and return immediately.
*/
// stop writeSync recursions with maxSubsequentCalls argument
// This is dangerous to use as it will lose the current data chunk
// and return immediately.
if (maxSubsequentCalls !== undefined && this._syncCalls > maxSubsequentCalls) {
/*
* comment next line if a whole loop block should only contain x `writeSync` calls
* (total flat vs. deep nested limit)
*/
// comment next line if a whole loop block should only contain x `writeSync` calls
// (total flat vs. deep nested limit)
this._syncCalls = 0;
return;
}
@@ -116,22 +112,18 @@ export class WriteBuffer extends Disposable {
}
this._isSyncWriting = true;
/*
* force sync processing on pending data chunks to avoid in-band data scrambling
* does the same as innerWrite but without event loop
* we have to do it here as single loop steps to not corrupt loop subject
* by another writeSync call triggered from _action
*/
// force sync processing on pending data chunks to avoid in-band data scrambling
// does the same as innerWrite but without event loop
// we have to do it here as single loop steps to not corrupt loop subject
// by another writeSync call triggered from _action
let chunk: string | Uint8Array | undefined;
while (chunk = this._writeBuffer.shift()) {
this._action(chunk);
const cb = this._callbacks.shift();
if (cb) cb();
}
/*
* reset to avoid reprocessing of chunks with scheduled innerWrite call
* stopping scheduled innerWrite by offset > length condition
*/
// reset to avoid reprocessing of chunks with scheduled innerWrite call
// stopping scheduled innerWrite by offset > length condition
this._pendingData = 0;
this._bufferOffset = 0x7FFFFFFF;
@@ -149,11 +141,9 @@ export class WriteBuffer extends Disposable {
if (!this._writeBuffer.length) {
this._bufferOffset = 0;
/*
* If this is the first write call after the user has done some input,
* parse it immediately to minimize input latency,
* otherwise schedule for the next event
*/
// If this is the first write call after the user has done some input,
// parse it immediately to minimize input latency,
// otherwise schedule for the next event
if (this._didUserInput) {
this._didUserInput = false;
this._pendingData += data.length;
@@ -244,19 +234,15 @@ export class WriteBuffer extends Disposable {
* throughput by eval'ing `startTime` upfront pulling at least one more chunk into the
* current microtask queue (executed before setTimeout).
*/
/*
* const continuation: (r: boolean) => void = performance.now() - startTime >=
* Constants.WRITE_TIMEOUT_MS
* ? r => setTimeout(() => this._innerWrite(0, r))
* : r => this._innerWrite(startTime, r);
*/
// const continuation: (r: boolean) => void = performance.now() - startTime >=
// Constants.WRITE_TIMEOUT_MS
// ? r => setTimeout(() => this._innerWrite(0, r))
// : r => this._innerWrite(startTime, r);
/*
* Handle exceptions synchronously to current band position, idea:
* 1. spawn a single microtask which we allow to throw hard
* 2. spawn a promise immediately resolving to `true`
* (executed on the same queue, thus properly aligned before continuation happens)
*/
// Handle exceptions synchronously to current band position, idea:
// 1. spawn a single microtask which we allow to throw hard
// 2. spawn a promise immediately resolving to `true`
// (executed on the same queue, thus properly aligned before continuation happens)
result.catch(err => {
queueMicrotask(() => {throw err;});
return Promise.resolve(false);
@@ -274,10 +260,8 @@ export class WriteBuffer extends Disposable {
}
}
if (this._writeBuffer.length > this._bufferOffset) {
/*
* Allow renderer to catch up before processing the next batch
* trim already processed chunks if we are above threshold
*/
// Allow renderer to catch up before processing the next batch
// trim already processed chunks if we are above threshold
if (this._bufferOffset > Constants.WRITE_BUFFER_LENGTH_THRESHOLD) {
this._writeBuffer = this._writeBuffer.slice(this._bufferOffset);
this._callbacks = this._callbacks.slice(this._bufferOffset);
+3 -5
View File
@@ -50,11 +50,9 @@ export function parseColor(data: string): [number, number, number] | undefined {
}
}
/*
* Named colors are currently not supported due to the large addition to the xterm.js bundle size
* they would add. In order to support named colors, we would need some way of optionally loading
* additional payloads so startup/download time is not bloated (see #3530).
*/
// Named colors are currently not supported due to the large addition to the xterm.js bundle size
// they would add. In order to support named colors, we would need some way of optionally loading
// additional payloads so startup/download time is not bloated (see #3530).
}
// pad hex output to requested bit width
+2 -4
View File
@@ -181,10 +181,8 @@ export class ApcHandler implements IApcHandler {
} else if (success) {
ret = this._handler(this._data);
if (ret instanceof Promise) {
/*
* need to hold data until `ret` got resolved
* dont care for errors, data will be freed anyway on next start
*/
// need to hold data until `ret` got resolved
// dont care for errors, data will be freed anyway on next start
return ret.then(res => {
this._data = '';
this._hitLimit = false;
+6 -10
View File
@@ -147,12 +147,10 @@ export class DcsHandler implements IDcsHandler {
constructor(private _handler: (data: string, params: IParams) => boolean | Promise<boolean>) { }
public hook(params: IParams): void {
/*
* since we need to preserve params until `unhook`, we have to clone it
* (only borrowed from parser and spans multiple parser states)
* perf optimization:
* clone only, if we have non empty params, otherwise stick with default
*/
// since we need to preserve params until `unhook`, we have to clone it
// (only borrowed from parser and spans multiple parser states)
// perf optimization:
// clone only, if we have non empty params, otherwise stick with default
this._params = (params.length > 1 || params.params[0]) ? params.clone() : EMPTY_PARAMS;
this._data = '';
this._hitLimit = false;
@@ -176,10 +174,8 @@ export class DcsHandler implements IDcsHandler {
} else if (success) {
ret = this._handler(this._data, this._params);
if (ret instanceof Promise) {
/*
* need to hold data and params until `ret` got resolved
* dont care for errors, data will be freed anyway on next start
*/
// need to hold data and params until `ret` got resolved
// dont care for errors, data will be freed anyway on next start
return ret.then(res => {
this._params = EMPTY_PARAMS;
this._data = '';
+6 -12
View File
@@ -2065,10 +2065,8 @@ async function throwsAsync(fn: () => Promise<any>, message?: string | undefined)
}
describe('EscapeSequenceParser - async', () => {
/*
* sequences: SGR 1;31 | hello SP | ESC %G | wor | ESC E | ld! | SGR 0 | EXE \r\n | $> | DCS 1;2 a [xyz] ST | OSC 1;foo=bar ST | APC X abc ST | FIN
* needed handlers: CSI m, PRINT, ESC %G, ESC E, EXE \r, EXE \n, OSC 1, APC X
*/
// sequences: SGR 1;31 | hello SP | ESC %G | wor | ESC E | ld! | SGR 0 | EXE \r\n | $> | DCS 1;2 a [xyz] ST | OSC 1;foo=bar ST | APC X abc ST | FIN
// needed handlers: CSI m, PRINT, ESC %G, ESC E, EXE \r, EXE \n, OSC 1, APC X
const INPUT = '\x1b[1;31mhello \x1b%Gwor\x1bEld!\x1b[0m\r\n$>\x1bP1;2axyz\x1b\\\x1b]1;foo=bar\x1b\\\x1b_Xabc\x1b\\FIN';
let RESULT: any[];
let parser: TestEscapeSequenceParser;
@@ -2157,10 +2155,8 @@ describe('EscapeSequenceParser - async', () => {
it('sync parse call does not work anymore', () => {
assert.notEqual(!parseSync(parser, INPUT), true);
assert.notDeepEqual(callstack, RESULT);
/*
* due to sync calling we should save exactly one saved stack
* proper continuation is not possible anymore, as we lost the promise resolve value
*/
// due to sync calling we should save exactly one saved stack
// proper continuation is not possible anymore, as we lost the promise resolve value
assert.equal(parser.trackedStack.length, 1);
});
it('improper continuation should throw', async () => {
@@ -2226,10 +2222,8 @@ describe('EscapeSequenceParser - async', () => {
// split to single char input
for (let i = 0; i < INPUT.length; ++i) {
/*
* Note: a single fully awaited parse call always ends in sync mode,
* which re-enables faster sync processing in the higher up callstack
*/
// Note: a single fully awaited parse call always ends in sync mode,
// which re-enables faster sync processing in the higher up callstack
await parseP(parser, INPUT[i]);
}
assert.deepEqual(callstack, RESULT);
+32 -50
View File
@@ -15,22 +15,20 @@ import { ApcParser } from 'common/parser/ApcParser';
/**
* VT commands done by the parser
*/
/*
* @vt: #Y ESC CSI "Control Sequence Introducer" "ESC [" "Start of a CSI sequence."
* @vt: #Y ESC OSC "Operating System Command" "ESC ]" "Start of an OSC sequence."
* @vt: #Y ESC DCS "Device Control String" "ESC P" "Start of a DCS sequence."
* @vt: #Y ESC ST "String Terminator" "ESC \" "Terminator used for string type sequences."
* @vt: #Y ESC PM "Privacy Message" "ESC ^" "Start of a privacy message."
* @vt: #Y ESC APC "Application Program Command" "ESC _" "Start of an APC sequence."
* @vt: #Y C1 CSI "Control Sequence Introducer" "\x9B" "Start of a CSI sequence."
* @vt: #Y C1 OSC "Operating System Command" "\x9D" "Start of an OSC sequence."
* @vt: #Y C1 DCS "Device Control String" "\x90" "Start of a DCS sequence."
* @vt: #Y C1 ST "String Terminator" "\x9C" "Terminator used for string type sequences."
* @vt: #Y C1 PM "Privacy Message" "\x9E" "Start of a privacy message."
* @vt: #Y C1 APC "Application Program Command" "\x9F" "Start of an APC sequence."
* @vt: #Y C0 NUL "Null" "\0, \x00" "NUL is ignored."
* @vt: #Y C0 ESC "Escape" "\e, \x1B" "Start of a sequence. Cancels any other sequence."
*/
// @vt: #Y ESC CSI "Control Sequence Introducer" "ESC [" "Start of a CSI sequence."
// @vt: #Y ESC OSC "Operating System Command" "ESC ]" "Start of an OSC sequence."
// @vt: #Y ESC DCS "Device Control String" "ESC P" "Start of a DCS sequence."
// @vt: #Y ESC ST "String Terminator" "ESC \" "Terminator used for string type sequences."
// @vt: #Y ESC PM "Privacy Message" "ESC ^" "Start of a privacy message."
// @vt: #Y ESC APC "Application Program Command" "ESC _" "Start of an APC sequence."
// @vt: #Y C1 CSI "Control Sequence Introducer" "\x9B" "Start of a CSI sequence."
// @vt: #Y C1 OSC "Operating System Command" "\x9D" "Start of an OSC sequence."
// @vt: #Y C1 DCS "Device Control String" "\x90" "Start of a DCS sequence."
// @vt: #Y C1 ST "String Terminator" "\x9C" "Terminator used for string type sequences."
// @vt: #Y C1 PM "Privacy Message" "\x9E" "Start of a privacy message."
// @vt: #Y C1 APC "Application Program Command" "\x9F" "Start of an APC sequence."
// @vt: #Y C0 NUL "Null" "\0, \x00" "NUL is ignored."
// @vt: #Y C0 ESC "Escape" "\e, \x1B" "Start of a sequence. Cancels any other sequence."
/**
* Table values are generated like this:
@@ -97,10 +95,8 @@ const NON_ASCII_PRINTABLE = 0xA0;
* Taken from https://vt100.net/emu/dec_ansi_parser.
*/
export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
/*
* table size:
* (ParserState.STATE_LENGTH - 1) << TableAccess.INDEX_STATE_SHIFT | NON_ASCII_PRINTABLE + 1
*/
// table size:
// (ParserState.STATE_LENGTH - 1) << TableAccess.INDEX_STATE_SHIFT | NON_ASCII_PRINTABLE + 1
const table: TransitionTable = new TransitionTable(4257);
// range macro for byte
@@ -504,11 +500,9 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._params.resetZdm();
this._collect = 0;
this.precedingJoinState = 0;
/*
* abort pending continuation from async handler
* Here the RESET type indicates, that the next parse call will
* ignore any saved stack, instead continues sync with next codepoint from GROUND
*/
// abort pending continuation from async handler
// Here the RESET type indicates, that the next parse call will
// ignore any saved stack, instead continues sync with next codepoint from GROUND
if (this._parseStack.state !== ParserStackType.NONE) {
this._parseStack.state = ParserStackType.RESET;
this._parseStack.handlers = []; // also release handlers ref
@@ -585,10 +579,8 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
// resume from async handler
if (this._parseStack.state) {
/*
* allow sync parser reset even in continuation mode
* Note: can be used to recover parser from improper continuation error below
*/
// allow sync parser reset even in continuation mode
// Note: can be used to recover parser from improper continuation error below
if (this._parseStack.state === ParserStackType.RESET) {
this._parseStack.state = ParserStackType.NONE;
start = this._parseStack.chunkPos + 1; // continue with next codepoint in GROUND
@@ -613,11 +605,9 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
throw new Error('improper continuation due to previous async handler, giving up parsing');
}
/*
* we have to resume the old handler loop if:
* - return value of the promise was `false`
* - handlers are not exhausted yet
*/
// we have to resume the old handler loop if:
// - return value of the promise was `false`
// - handlers are not exhausted yet
const handlers = this._parseStack.handlers;
let handlerPos = this._parseStack.handlerPos - 1;
switch (this._parseStack.state) {
@@ -804,10 +794,8 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
const handlers = this._csiHandlers[this._collect << 8 | code];
let j = handlers ? handlers.length - 1 : -1;
for (; j >= 0; j--) {
/*
* true means success and to stop bubbling
* a promise indicates an async handler that needs to finish before progressing
*/
// true means success and to stop bubbling
// a promise indicates an async handler that needs to finish before progressing
handlerResult = handlers[j](this._params);
if (handlerResult === true) {
break;
@@ -845,10 +833,8 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
const handlersEsc = this._escHandlers[this._collect << 8 | code];
let jj = handlersEsc ? handlersEsc.length - 1 : -1;
for (; jj >= 0; jj--) {
/*
* true means success and to stop bubbling
* a promise indicates an async handler that needs to finish before progressing
*/
// true means success and to stop bubbling
// a promise indicates an async handler that needs to finish before progressing
handlerResult = handlersEsc[jj]();
if (handlerResult === true) {
break;
@@ -870,10 +856,8 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._dcsParser.hook(this._collect << 8 | code, this._params);
break;
case ParserAction.DCS_PUT:
/*
* inner loop - exit DCS_PUT: 0x18, 0x1a, 0x1b, 0x7f, 0x80 - 0x9f
* unhook triggered by: 0x1b, 0x9c (success) and 0x18, 0x1a (abort)
*/
// inner loop - exit DCS_PUT: 0x18, 0x1a, 0x1b, 0x7f, 0x80 - 0x9f
// unhook triggered by: 0x1b, 0x9c (success) and 0x18, 0x1a (abort)
for (let j = i + 1; ; ++j) {
if (j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {
this._dcsParser.put(data, i, j);
@@ -921,10 +905,8 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._apcParser.start(this._collect << 8 | code);
break;
case ParserAction.APC_PUT:
/*
* inner loop - exit APC_PUT: 0x18, 0x1a, 0x1b, 0x9c
* allowed: 00/08 .. 00/13, 02/00 .. 07/14 + NON_ASCII_PRINTABLE
*/
// inner loop - exit APC_PUT: 0x18, 0x1a, 0x1b, 0x9c
// allowed: 00/08 .. 00/13, 02/00 .. 07/14 + NON_ASCII_PRINTABLE
for (let j = i + 1; ; ++j) {
if (j < length && (
(data[j] >= 0x20 && data[j] < 0x7f) || (data[j] >= 0x08 && data[j] < 0x0e) || data[j] >= NON_ASCII_PRINTABLE
+8 -14
View File
@@ -133,11 +133,9 @@ export class OscParser implements IOscParser {
}
// do nothing if command was faulty
if (this._state !== OscState.ABORT) {
/*
* if we are still in ID state and get an early end
* means that the command has no payload thus we still have
* to announce START and send END right after
*/
// if we are still in ID state and get an early end
// means that the command has no payload thus we still have
// to announce START and send END right after
if (this._state === OscState.ID) {
this._start();
}
@@ -168,11 +166,9 @@ export class OscParser implements IOscParser {
}
j--;
}
/*
* cleanup left over handlers
* we always have to call .end for proper cleanup,
* here we use `success` to indicate whether a handler should execute
*/
// cleanup left over handlers
// we always have to call .end for proper cleanup,
// here we use `success` to indicate whether a handler should execute
for (; j >= 0; j--) {
handlerResult = this._active[j].end(false);
if (handlerResult instanceof Promise) {
@@ -226,10 +222,8 @@ export class OscHandler implements IOscHandler {
} else if (success) {
ret = this._handler(this._data);
if (ret instanceof Promise) {
/*
* need to hold data until `ret` got resolved
* dont care for errors, data will be freed anyway on next start
*/
// need to hold data until `ret` got resolved
// dont care for errors, data will be freed anyway on next start
return ret.then(res => {
this._data = '';
this._hitLimit = false;
+6 -12
View File
@@ -103,28 +103,22 @@ export class BufferService extends Disposable implements IBufferService {
buffer.ydisp++;
}
} else {
/*
* When the buffer is full and the user has scrolled up, keep the text
* stable unless ydisp is right at the top
*/
// When the buffer is full and the user has scrolled up, keep the text
// stable unless ydisp is right at the top
if (this.isUserScrolling) {
buffer.ydisp = Math.max(buffer.ydisp - 1, 0);
}
}
} else {
/*
* scrollTop is non-zero which means no line will be going to the
* scrollback, instead we can just shift them in-place.
*/
// scrollTop is non-zero which means no line will be going to the
// scrollback, instead we can just shift them in-place.
const scrollRegionHeight = bottomRow - topRow + 1 /* as it's zero-based */;
buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);
buffer.lines.set(bottomRow, newLine.clone());
}
/*
* Move the viewport to the bottom of the buffer unless the user is
* scrolling.
*/
// Move the viewport to the bottom of the buffer unless the user is
// scrolling.
if (!this.isUserScrolling) {
buffer.ydisp = buffer.ybase;
}
+2 -4
View File
@@ -4,12 +4,10 @@
*
* This was heavily inspired from microsoft/vscode's dependency injection system (MIT).
*/
/*
*---------------------------------------------------------------------------------------------
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------
*/
*--------------------------------------------------------------------------------------------*/
import { IInstantiationService, IServiceIdentifier } from 'common/services/Services';
import { getServiceDependencies } from 'common/services/ServiceRegistry';
+2 -4
View File
@@ -16,10 +16,8 @@ interface IConsole {
warn: LogType;
}
/*
* console is available on both node.js and browser contexts but the common
* module doesn't depend on them so we need to explicitly declare it.
*/
// console is available on both node.js and browser contexts but the common
// module doesn't depend on them so we need to explicitly declare it.
declare const console: IConsole;
const optionsKeyToLogLevel: { [key: string]: LogLevelEnum } = {
+6 -10
View File
@@ -105,10 +105,8 @@ function eventCode(e: ICoreMouseEvent, isSGR: boolean): number {
if (e.action === CoreMouseAction.MOVE) {
code |= CoreMouseAction.MOVE;
} else if (e.action === CoreMouseAction.UP && !isSGR) {
/*
* special case - only SGR can report button on release
* all others have to go with NONE
*/
// special case - only SGR can report button on release
// all others have to go with NONE
code |= CoreMouseButton.NONE;
}
}
@@ -128,12 +126,10 @@ const DEFAULT_ENCODINGS: { [key: string]: CoreMouseEncoding } = {
*/
DEFAULT: (e: ICoreMouseEvent) => {
const params = [eventCode(e, false) + 32, e.col + 32, e.row + 32];
/*
* supress mouse report if we exceed addressible range
* Note this is handled differently by emulators
* - xterm: sends 0;0 coords instead
* - vte, konsole: no report
*/
// supress mouse report if we exceed addressible range
// Note this is handled differently by emulators
// - xterm: sends 0;0 coords instead
// - vte, konsole: no report
if (params[0] > 255 || params[1] > 255 || params[2] > 255) {
return '';
}
+2 -4
View File
@@ -90,10 +90,8 @@ export class OptionsService extends Disposable implements IOptionsService {
this.options = { ... defaultOptions };
this._setupOptions();
/*
* Clear out options that could link outside xterm.js as they could easily cause an embedder
* memory leak
*/
// Clear out options that could link outside xterm.js as they could easily cause an embedder
// memory leak
this._register(toDisposable(() => {
this.rawOptions.linkHandler = null;
this.rawOptions.documentOverride = null;
+2 -4
View File
@@ -4,12 +4,10 @@
*
* This was heavily inspired from microsoft/vscode's dependency injection system (MIT).
*/
/*
*---------------------------------------------------------------------------------------------
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------
*/
*--------------------------------------------------------------------------------------------*/
import { IServiceIdentifier } from 'common/services/Services';
+7 -11
View File
@@ -78,20 +78,16 @@ export class UnicodeService implements IUnicodeService {
// surrogate pair first
if (0xD800 <= code && code <= 0xDBFF) {
if (++i >= length) {
/*
* this should not happen with strings retrieved from
* Buffer.translateToString as it converts from UTF-32
* and therefore always should contain the second part
* for any other string we still have to handle it somehow:
* simply treat the lonely surrogate first as a single char (UCS-2 behavior)
*/
// this should not happen with strings retrieved from
// Buffer.translateToString as it converts from UTF-32
// and therefore always should contain the second part
// for any other string we still have to handle it somehow:
// simply treat the lonely surrogate first as a single char (UCS-2 behavior)
return result + this.wcwidth(code);
}
const second = s.charCodeAt(i);
/*
* convert surrogate pair to high codepoint only for valid second part (UTF-16)
* otherwise treat them independently (UCS-2 behavior)
*/
// convert surrogate pair to high codepoint only for valid second part (UTF-16)
// otherwise treat them independently (UCS-2 behavior)
if (0xDC00 <= second && second <= 0xDFFF) {
code = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
} else {