Merge branch 'master' into 4198_kitty
This commit is contained in:
@@ -176,6 +176,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
|
||||
x = Math.max(x, MINIMUM_COLS);
|
||||
y = Math.max(y, MINIMUM_ROWS);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -716,6 +716,22 @@ describe('InputHandler', () => {
|
||||
await inputHandler.parseP('\x1b[22m');
|
||||
assert.equal(!!inputHandler.curAttrData.isDim(), false);
|
||||
});
|
||||
it('SGR 221 resets bold only (kitty)', async () => {
|
||||
await inputHandler.parseP('\x1b[1;2m');
|
||||
assert.equal(!!inputHandler.curAttrData.isBold(), true);
|
||||
assert.equal(!!inputHandler.curAttrData.isDim(), true);
|
||||
await inputHandler.parseP('\x1b[221m');
|
||||
assert.equal(!!inputHandler.curAttrData.isBold(), false);
|
||||
assert.equal(!!inputHandler.curAttrData.isDim(), true);
|
||||
});
|
||||
it('SGR 222 resets faint only (kitty)', async () => {
|
||||
await inputHandler.parseP('\x1b[1;2m');
|
||||
assert.equal(!!inputHandler.curAttrData.isBold(), true);
|
||||
assert.equal(!!inputHandler.curAttrData.isDim(), true);
|
||||
await inputHandler.parseP('\x1b[222m');
|
||||
assert.equal(!!inputHandler.curAttrData.isBold(), true);
|
||||
assert.equal(!!inputHandler.curAttrData.isDim(), false);
|
||||
});
|
||||
it('italic', async () => {
|
||||
await inputHandler.parseP('\x1b[3m');
|
||||
assert.equal(!!inputHandler.curAttrData.isItalic(), true);
|
||||
|
||||
@@ -2538,6 +2538,8 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* | 53 | Overlined. | #Y |
|
||||
* | 55 | Not Overlined. | #Y |
|
||||
* | 58 | Underline color: Extended color. | #P[Support for RGB and indexed colors, see below.] |
|
||||
* | 221 | Not bold (kitty extension). | #Y |
|
||||
* | 222 | Not faint (kitty extension). | #Y |
|
||||
* | 90 - 97 | Bright foreground color (analogous to 30 - 37). | #Y |
|
||||
* | 100 - 107 | Bright background color (analogous to 40 - 47). | #Y |
|
||||
*
|
||||
@@ -2670,6 +2672,12 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
} else if (p === 55) {
|
||||
// not overline
|
||||
attr.bg &= ~BgFlags.OVERLINE;
|
||||
} else if (p === 221) {
|
||||
// not bold (kitty extension)
|
||||
attr.fg &= ~FgFlags.BOLD;
|
||||
} else if (p === 222) {
|
||||
// not faint (kitty extension)
|
||||
attr.bg &= ~BgFlags.DIM;
|
||||
} else if (p === 59) {
|
||||
attr.extended = attr.extended.clone();
|
||||
attr.extended.underlineColor = -1;
|
||||
|
||||
@@ -106,5 +106,24 @@ describe('WriteBuffer', () => {
|
||||
wb.writeSync('1', 10);
|
||||
assert.equal(last, '11'); // 1 + 10 sub calls = 11
|
||||
});
|
||||
it('flushSync processes all pending writes', done => {
|
||||
wb.write('a', () => { cbStack.push('a'); });
|
||||
wb.write('b', () => { cbStack.push('b'); });
|
||||
wb.write('c', () => { cbStack.push('c'); });
|
||||
wb.flushSync();
|
||||
assert.deepEqual(stack, ['a', 'b', 'c']);
|
||||
assert.deepEqual(cbStack, ['a', 'b', 'c']);
|
||||
wb.write('x', () => { cbStack.push('x'); });
|
||||
wb.write('', () => {
|
||||
assert.deepEqual(stack, ['a', 'b', 'c', 'x', '']);
|
||||
assert.deepEqual(cbStack, ['a', 'b', 'c', 'x']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('flushSync with no pending writes is a no-op', () => {
|
||||
wb.flushSync();
|
||||
assert.deepEqual(stack, []);
|
||||
assert.deepEqual(cbStack, []);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,6 +54,38 @@ export class WriteBuffer extends Disposable {
|
||||
this._didUserInput = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes all pending writes synchronously. This is useful when you need to
|
||||
* ensure all queued data is processed before performing an operation that
|
||||
* depends upon everything being parsed like resize.
|
||||
*
|
||||
* Note: This is unreliable with async parser handlers as it does not wait for
|
||||
* promises to resolve.
|
||||
*/
|
||||
public flushSync(): void {
|
||||
// exit early if another sync write loop is active
|
||||
if (this._isSyncWriting) {
|
||||
return;
|
||||
}
|
||||
this._isSyncWriting = true;
|
||||
|
||||
// Process all pending chunks synchronously
|
||||
let chunk: string | Uint8Array | undefined;
|
||||
while (chunk = this._writeBuffer.shift()) {
|
||||
this._action(chunk);
|
||||
const cb = this._callbacks.shift();
|
||||
if (cb) cb();
|
||||
}
|
||||
|
||||
// Reset buffer state
|
||||
this._pendingData = 0;
|
||||
this._bufferOffset = 0x7FFFFFFF;
|
||||
this._writeBuffer.length = 0;
|
||||
this._callbacks.length = 0;
|
||||
|
||||
this._isSyncWriting = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Unreliable, to be removed soon.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user