Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
041d3bc3db | ||
|
|
ea2a506142 | ||
|
|
5527814e08 | ||
|
|
d47ea40010 | ||
|
|
c78f77cc17 | ||
|
|
ebe7af5bf4 | ||
|
|
faaa549355 | ||
|
|
1e554992f6 |
+27
-19
@@ -11,9 +11,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
./addons/addon-webgl/out/* \
|
||||
./addons/addon-webgl/out-*st/*
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: compressed-build.zip
|
||||
@@ -79,9 +79,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
@@ -100,16 +100,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm ci
|
||||
- uses: actions/download-artifact@v7
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -129,7 +129,6 @@ jobs:
|
||||
exit $EXIT_CODE
|
||||
|
||||
test-unit:
|
||||
needs: build
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -137,16 +136,21 @@ jobs:
|
||||
runs-on: [ubuntu, macos, windows]
|
||||
runs-on: ${{ matrix.runs-on }}-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm ci
|
||||
- uses: actions/download-artifact@v7
|
||||
- name: Wait for build job
|
||||
uses: NathanFirmo/wait-for-other-job@v1.1.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
job: build
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -162,7 +166,6 @@ jobs:
|
||||
run: npm run test-unit --forbid-only
|
||||
|
||||
test-integration:
|
||||
needs: build
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -171,9 +174,9 @@ jobs:
|
||||
browser: [chromium, firefox, webkit]
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}.x
|
||||
cache: 'npm'
|
||||
@@ -182,7 +185,12 @@ jobs:
|
||||
npm ci
|
||||
- name: Install playwright
|
||||
run: npx playwright install --with-deps ${{ matrix.browser }}
|
||||
- uses: actions/download-artifact@v7
|
||||
- name: Wait for build job
|
||||
uses: NathanFirmo/wait-for-other-job@v1.1.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
job: build
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -232,9 +240,9 @@ jobs:
|
||||
matrix:
|
||||
node-version: [22]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}.x
|
||||
cache: 'npm'
|
||||
@@ -243,7 +251,7 @@ jobs:
|
||||
npm ci
|
||||
- name: Install playwright
|
||||
run: npx playwright install
|
||||
- uses: actions/download-artifact@v7
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
|
||||
@@ -24,12 +24,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v3
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -18,9 +18,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
|
||||
@@ -10,9 +10,9 @@ jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
|
||||
@@ -15,7 +15,7 @@ test.beforeAll(async ({ browser }) => {
|
||||
});
|
||||
test.afterAll(async () => await ctx.page.close());
|
||||
|
||||
test.describe('AttachAddon', () => {
|
||||
test.describe('Search Tests', () => {
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await ctx.proxy.reset();
|
||||
|
||||
@@ -78,43 +78,13 @@ export class BrowserClipboardProvider implements IClipboardProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Once the base64 handling on Uint8Arrays is more common,
|
||||
* remove the btoa/atob fallbacks below.
|
||||
*/
|
||||
interface IUint8ArrayB64 extends Uint8Array {
|
||||
toBase64(): string;
|
||||
}
|
||||
interface IUint8ArrayB64Ctor extends Uint8ArrayConstructor {
|
||||
fromBase64(s: string): IUint8ArrayB64;
|
||||
}
|
||||
|
||||
export class Base64 implements IBase64 {
|
||||
public encodeText(data: string): string {
|
||||
const bytes = new TextEncoder().encode(data) as IUint8ArrayB64;
|
||||
if (bytes.toBase64 !== undefined) {
|
||||
return bytes.toBase64();
|
||||
}
|
||||
let bin = '';
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
bin += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return btoa(bin);
|
||||
return btoa(data);
|
||||
}
|
||||
public decodeText(data: string): string {
|
||||
if ((Uint8Array as IUint8ArrayB64Ctor).fromBase64 !== undefined) {
|
||||
try {
|
||||
return new TextDecoder().decode((Uint8Array as IUint8ArrayB64Ctor).fromBase64(data));
|
||||
} catch {}
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
const bin = atob(data);
|
||||
const bytes = new Uint8Array(bin.length);
|
||||
for (let i = 0; i < bin.length; ++i) {
|
||||
bytes[i] = bin.charCodeAt(i);
|
||||
}
|
||||
return new TextDecoder().decode(bytes);
|
||||
return atob(data);
|
||||
} catch {}
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ test.describe('ClipboardAddon', () => {
|
||||
await ctx.page.context().grantPermissions(['clipboard-read', 'clipboard-write']);
|
||||
}
|
||||
await ctx.page.evaluate(`
|
||||
window.term.reset();
|
||||
window.term.reset()
|
||||
window.clipboard?.dispose();
|
||||
window.clipboard = new ClipboardAddon();
|
||||
window.term.loadAddon(window.clipboard);
|
||||
@@ -92,22 +92,4 @@ test.describe('ClipboardAddon', () => {
|
||||
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('non-ASCII', () => {
|
||||
const testDataEncoded = '4oKsbWzDpMO8dMOf';
|
||||
const testDataDecoded = '€mläütß';
|
||||
test('write simple string', async () => {
|
||||
await ctx.proxy.write(`\x1b]52;c;${testDataEncoded}\x07`);
|
||||
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), testDataDecoded);
|
||||
});
|
||||
test('read simple string', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.data2 = [];
|
||||
window.term.onData(e => data2.push(e));
|
||||
`);
|
||||
await ctx.page.evaluate((d) => window.navigator.clipboard.writeText(d), testDataDecoded);
|
||||
await ctx.proxy.write(`\x1b]52;c;?\x07`);
|
||||
deepEqual(await ctx.page.evaluate('window.data2'), [`\x1b]52;c;${testDataEncoded}\x07`]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -90,7 +90,7 @@ terminal.loadAddon(imageAddon);
|
||||
therefore palette animations cannot be used.
|
||||
|
||||
- **SIXEL Raster Attributes Handling**
|
||||
If raster attributes were found in the SIXEL data (level 2), the image will always be truncated to the given height/width extent. We deviate here from the specification on purpose, as it allows several processing optimizations. For level 1 SIXEL data without any raster attributes the image can freely grow in width and height up to the last data byte, which has a much higher processing penalty. In general encoding libraries should not create level 1 data anymore and should not produce pixel information beyond the announced height/width extent. Both is discouraged by the >30 years old specification.
|
||||
If raster attributes were found in the SIXEL data (level 2), the image will always be truncated to the given height/width extend. We deviate here from the specification on purpose, as it allows several processing optimizations. For level 1 SIXEL data without any raster attributes the image can freely grow in width and height up to the last data byte, which has a much higher processing penalty. In general encoding libraries should not create level 1 data anymore and should not produce pixel information beyond the announced height/width extend. Both is discouraged by the >30 years old specification.
|
||||
|
||||
Currently the SIXEL implementation of the addon does not take custom pixel sizes into account, a SIXEL pixel will map 1:1 to a screen pixel.
|
||||
|
||||
@@ -149,9 +149,9 @@ The addon provides the following API endpoints to retrieve raw image data as can
|
||||
|
||||
### Memory Usage
|
||||
|
||||
The addon does most image processing in JavaScript and therefore can occupy a rather big amount of memory. To get an idea where the memory gets eaten, let's look at the data flow and processing steps:
|
||||
- Incoming image data chunk at `term.write` (terminal)
|
||||
`term.write` might stack up incoming chunks. To circumvent this, you will need proper flow control (see xterm.js docs). Note that with image output it is more likely to run into this issue, as it can create lots of MBs in very short time.
|
||||
The addon does most image processing in Javascript and therefore can occupy a rather big amount of memory. To get an idea where the memory gets eaten, lets look at the data flow and processing steps:
|
||||
- Incomming image data chunk at `term.write` (terminal)
|
||||
`term.write` might stock up incoming chunks. To circumvent this, you will need proper flow control (see xterm.js docs). Note that with image output it is more likely to run into this issue, as it can create lots of MBs in very short time.
|
||||
- Sequence Parser (terminal)
|
||||
The parser operates on a buffer containing up to 2^17 codepoints (~0.5 MB).
|
||||
- Sequence Handler - Chunk Decoding (addon)
|
||||
@@ -177,18 +177,18 @@ const totalActive = storageBytes + decodingBytes;
|
||||
```
|
||||
|
||||
Note that browsers have offloading tricks for rarely touched memory segments, esp. `storageBytes` might not directly translate into real memory usage. Usage peaks will happen during active decoding of multiple big images due to the need of 2 full pixel buffers at the same time, which cannot be offloaded. Thus you may want to keep an eye on `pixelLimit` under limited memory conditions.
|
||||
Further note that the formulas above do not respect the JavaScript object's overhead. Compared to the raw buffer needs the bookkeeping by these objects is rather small (<<5%).
|
||||
Further note that the formulas above do not respect the Javascript object's overhead. Compared to the raw buffer needs the book keeping by these objects is rather small (<<5%).
|
||||
|
||||
_Why should I care about memory usage at all?_
|
||||
Well you don't have to, and it probably will just work fine with the addon defaults. But for bigger integrations, where much more data is held in the JavaScript context (like multiple terminals on one page), it is likely to hit the engine's memory limit sooner or later under decoding and/or storage pressure.
|
||||
Well you don't have to, and it probably will just work fine with the addon defaults. But for bigger integrations, where much more data is held in the Javascript context (like multiple terminals on one page), it is likely to hit the engine's memory limit sooner or later under decoding and/or storage pressure.
|
||||
|
||||
_How can I adjust the memory usage?_
|
||||
- `pixelLimit`
|
||||
A constructor setting, thus you would have to anticipate, whether (multiple) terminals in your page gonna do lots of concurrent decoding. Since this is normally not the case and the memory usage only peaks temporarily, a rather high value should work even with multiple terminals in one page.
|
||||
A constructor setting, thus you would have to anticipate, whether (multiple) terminals in your page gonna do lots of concurrent decoding. Since this is normally not the case and the memory usage is only temporarily peaking, a rather high value should work even with multiple terminals in one page.
|
||||
- `storageLimit`
|
||||
A constructor and a runtime setting. In conjunction with `storageUsage` you can do runtime checks and adjust the limit to your needs. If you have to lower the limit below the current usage, images will be removed in FIFO order and may turn into a placeholder in the terminal's scrollback (if `showPlaceholder` is set). When adjusting keep in mind to leave enough room for peak memory use during decoding.
|
||||
A constructor and a runtime setting. In conjunction with `storageUsage` you can do runtime checks and adjust the limit to your needs. If you have to lower the limit below the current usage, images will be removed in FIFO order and may turn into a placeholder in the terminal's scrollback (if `showPlaceholder` is set). When adjusting keep in mind to leave enough room for memory peaking for decoding.
|
||||
- `sixelSizeLimit | iipSizeLimit | kittySizeLimit`
|
||||
Constructor settings. This has only a small impact on peak memory during decoding. It is meant to avoid processing of overly big or broken image sequences at an earlier phase, thus may stop the invoked decoders from entering memory intensive tasks for potentially invalid data.
|
||||
Constructor settings. This has only a small impact on peaking memory during decoding. It is meant to avoid processing of overly big or broken image sequences at an earlier phase, thus may stop the invoked decoders from entering memory intensive tasks for potentially invalid data.
|
||||
|
||||
|
||||
### Terminal Interaction
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import type { ITerminalAddon, IDisposable } from '@xterm/xterm';
|
||||
import type { ImageAddon as IImageApi } from '@xterm/addon-image';
|
||||
import { Emitter, type IEvent } from 'common/primitives/Event';
|
||||
import { Emitter, type IEvent } from 'common/Event';
|
||||
import { IIPHandler } from './IIPHandler';
|
||||
import { ImageRenderer } from './ImageRenderer';
|
||||
import { ImageStorage, CELL_SIZE_DEFAULT } from './ImageStorage';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { toRGBA8888 } from 'sixel/lib/Colors';
|
||||
import { IDisposable } from '@xterm/xterm';
|
||||
import { ICellSize, ImageLayer, ITerminalExt, IImageSpec, IRenderDimensions, IRenderService } from './Types';
|
||||
import { Disposable, MutableDisposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||
|
||||
const enum Constants {
|
||||
PLACEHOLDER_LENGTH = 4096,
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
import { IDisposable, IMarker, Terminal } from '@xterm/xterm';
|
||||
|
||||
// private imports from base repo we build against
|
||||
import { Attributes, BgFlags, Content, ExtFlags, UnderlineStyle } from 'common/primitives/buffer/Constants';
|
||||
import type { AttributeData } from 'common/primitives/buffer/AttributeData';
|
||||
import type { IParams, IDcsHandler, IOscHandler, IApcHandler, IEscapeSequenceParser } from 'common/primitives/parser/Types';
|
||||
import { Attributes, BgFlags, Content, ExtFlags, UnderlineStyle } from 'common/buffer/Constants';
|
||||
import type { AttributeData } from 'common/buffer/AttributeData';
|
||||
import type { IParams, IDcsHandler, IOscHandler, IApcHandler, IEscapeSequenceParser } from 'common/parser/Types';
|
||||
import type { IInputHandler } from 'common/Types';
|
||||
import type { IBufferLine, IExtendedAttrs } from 'common/primitives/buffer/Types';
|
||||
import type { IBufferLine, IExtendedAttrs } from 'common/buffer/Types';
|
||||
import type { ITerminal, ReadonlyColorSet } from 'browser/Types';
|
||||
import type { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||
import type { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import type { Terminal, ITerminalAddon, IDisposable } from '@xterm/xterm';
|
||||
import type { ProgressAddon as IProgressApi, IProgressState } from '@xterm/addon-progress';
|
||||
import type { Emitter, IEvent } from 'common/primitives/Event';
|
||||
import type { Emitter, IEvent } from 'common/Event';
|
||||
|
||||
|
||||
const enum ProgressType {
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { DecorationManager } from './DecorationManager';
|
||||
import { SearchEngine } from './SearchEngine';
|
||||
import { SearchLineCache } from './SearchLineCache';
|
||||
import { Terminal } from 'browser/public/Terminal';
|
||||
import type { ISearchDecorationOptions } from '@xterm/addon-search';
|
||||
import type { IDecorationOptions } from '@xterm/xterm';
|
||||
import { DisposableStore } from 'common/primitives/Lifecycle';
|
||||
|
||||
function writeP(terminal: Terminal, data: string): Promise<void> {
|
||||
return new Promise(r => terminal.write(data, r));
|
||||
}
|
||||
|
||||
describe('DecorationManager', () => {
|
||||
let store: DisposableStore;
|
||||
let terminal: Terminal;
|
||||
let decorationManager: DecorationManager;
|
||||
|
||||
beforeEach(() => {
|
||||
store = new DisposableStore();
|
||||
terminal = store.add(new Terminal({ cols: 10, rows: 5 }));
|
||||
decorationManager = store.add(new DecorationManager(terminal));
|
||||
});
|
||||
|
||||
it('should split highlight decorations for a wrapped match', async () => {
|
||||
await writeP(terminal, '0123456789abcde');
|
||||
const searchEngine = new SearchEngine(terminal, store.add(new SearchLineCache(terminal)));
|
||||
const match = searchEngine.find('9abc', 0, 0);
|
||||
assert.ok(match);
|
||||
|
||||
const decorationOptions: IDecorationOptions[] = [];
|
||||
const registerDecoration = terminal.registerDecoration.bind(terminal);
|
||||
terminal.registerDecoration = (options: IDecorationOptions) => {
|
||||
decorationOptions.push(options);
|
||||
return registerDecoration(options);
|
||||
};
|
||||
|
||||
const options: ISearchDecorationOptions = {
|
||||
matchOverviewRuler: '#ff0000',
|
||||
activeMatchColorOverviewRuler: '#00ff00'
|
||||
};
|
||||
decorationManager.createHighlightDecorations([match], options);
|
||||
|
||||
assert.strictEqual(decorationOptions.length, 2);
|
||||
assert.strictEqual(decorationOptions[0].x, 9);
|
||||
assert.strictEqual(decorationOptions[0].width, 1);
|
||||
assert.strictEqual(decorationOptions[1].x, 0);
|
||||
assert.strictEqual(decorationOptions[1].width, 3);
|
||||
|
||||
const withOverviewRuler = decorationOptions.filter(o => o.overviewRulerOptions !== undefined);
|
||||
assert.strictEqual(withOverviewRuler.length, 2);
|
||||
});
|
||||
|
||||
it('should only add one overview ruler marker per buffer line', async () => {
|
||||
await writeP(terminal, 'abcdefghij');
|
||||
const decorationOptions: IDecorationOptions[] = [];
|
||||
const registerDecoration = terminal.registerDecoration.bind(terminal);
|
||||
terminal.registerDecoration = (options: IDecorationOptions) => {
|
||||
decorationOptions.push(options);
|
||||
return registerDecoration(options);
|
||||
};
|
||||
|
||||
const options: ISearchDecorationOptions = {
|
||||
matchOverviewRuler: '#ff0000',
|
||||
activeMatchColorOverviewRuler: '#00ff00'
|
||||
};
|
||||
decorationManager.createHighlightDecorations([
|
||||
{ term: 'a', col: 0, row: 0, size: 1 },
|
||||
{ term: 'f', col: 5, row: 0, size: 1 }
|
||||
], options);
|
||||
|
||||
const withOverviewRuler = decorationOptions.filter(o => o.overviewRulerOptions !== undefined);
|
||||
assert.strictEqual(withOverviewRuler.length, 1);
|
||||
assert.strictEqual(withOverviewRuler[0].x, 0);
|
||||
});
|
||||
});
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';
|
||||
import type { ISearchDecorationOptions } from '@xterm/addon-search';
|
||||
import { dispose, Disposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { dispose, Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import type { ISearchResult } from './SearchEngine';
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';
|
||||
import type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';
|
||||
import { Emitter, type IEvent } from 'common/primitives/Event';
|
||||
import { Disposable, MutableDisposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { disposableTimeout } from 'common/primitives/Async';
|
||||
import { Emitter, type IEvent } from 'common/Event';
|
||||
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||
import { disposableTimeout } from 'common/Async';
|
||||
import { SearchLineCache } from './SearchLineCache';
|
||||
import { SearchState } from './SearchState';
|
||||
import { SearchEngine, type ISearchResult } from './SearchEngine';
|
||||
@@ -142,14 +142,12 @@ export class SearchAddon extends Disposable implements ITerminalAddon, ISearchAp
|
||||
}
|
||||
prevResult = result;
|
||||
results.push(prevResult);
|
||||
const cols = this._terminal.cols;
|
||||
let nextCol = prevResult.col + prevResult.size;
|
||||
let nextRow = prevResult.row;
|
||||
if (nextCol >= cols) {
|
||||
nextRow += Math.floor(nextCol / cols);
|
||||
nextCol = nextCol % cols;
|
||||
}
|
||||
result = this._engine.find(term, nextRow, nextCol, searchOptions);
|
||||
result = this._engine.find(
|
||||
term,
|
||||
prevResult.col + prevResult.term.length >= this._terminal.cols ? prevResult.row + 1 : prevResult.row,
|
||||
prevResult.col + prevResult.term.length >= this._terminal.cols ? 0 : prevResult.col + 1,
|
||||
searchOptions
|
||||
);
|
||||
}
|
||||
|
||||
this._resultTracker.updateResults(results, this._highlightLimit);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { SearchEngine } from './SearchEngine';
|
||||
import { SearchLineCache } from './SearchLineCache';
|
||||
import { Terminal } from 'browser/public/Terminal';
|
||||
import type { ISearchOptions } from '@xterm/addon-search';
|
||||
import { DisposableStore } from 'common/primitives/Lifecycle';
|
||||
import { DisposableStore } from 'common/Lifecycle';
|
||||
|
||||
function writeP(terminal: Terminal, data: string): Promise<void> {
|
||||
return new Promise(r => terminal.write(data, r));
|
||||
|
||||
@@ -60,7 +60,7 @@ export class SearchEngine {
|
||||
this._terminal.clearSelection();
|
||||
return undefined;
|
||||
}
|
||||
if (startCol >= this._terminal.cols) {
|
||||
if (startCol > this._terminal.cols) {
|
||||
throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { assert } from 'chai';
|
||||
import { SearchLineCache, LineCacheEntry } from './SearchLineCache';
|
||||
import { Terminal } from 'browser/public/Terminal';
|
||||
import { timeout } from 'common/primitives/Async';
|
||||
import { timeout } from 'common/Async';
|
||||
|
||||
function writeP(terminal: Terminal, data: string): Promise<void> {
|
||||
return new Promise(r => terminal.write(data, r));
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import type { Terminal } from '@xterm/xterm';
|
||||
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { disposableTimeout } from 'common/primitives/Async';
|
||||
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||
import { disposableTimeout } from 'common/Async';
|
||||
|
||||
export type LineCacheEntry = [
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import type { ISearchResultChangeEvent } from '@xterm/addon-search';
|
||||
import type { IDisposable } from '@xterm/xterm';
|
||||
import { Emitter, type IEvent } from 'common/primitives/Event';
|
||||
import { Disposable } from 'common/primitives/Lifecycle';
|
||||
import { Emitter, type IEvent } from 'common/Event';
|
||||
import { Disposable } from 'common/Lifecycle';
|
||||
import type { ISearchResult } from './SearchEngine';
|
||||
|
||||
/**
|
||||
|
||||
@@ -414,24 +414,10 @@ test.describe('Search Tests', () => {
|
||||
});
|
||||
|
||||
test.describe('Regression tests', () => {
|
||||
test('should advance highlight-all scan by buffer match size for wide characters', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.resize(3, 5);
|
||||
await ctx.proxy.write('𝄞𝄞𝄞');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('𝄞', { decorations: { activeMatchColorOverviewRuler: '#ff0000', matchOverviewRuler: '#ffff00' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 }
|
||||
]);
|
||||
await ctx.proxy.resize(80, 24);
|
||||
});
|
||||
|
||||
test.describe('#2444 wrapped line content not being found', () => {
|
||||
let fixture: string;
|
||||
test.beforeAll(async () => {
|
||||
fixture = (await new Promise<Buffer>((res, rej) => readFile(resolve(__dirname, '../fixtures/issue-2444'), (err, data) => err ? rej(err) : res(data)))).toString();
|
||||
fixture = (await new Promise<Buffer>(r => readFile(resolve(__dirname, '../fixtures/issue-2444'), (err, data) => r(data)))).toString();
|
||||
if (process.platform !== 'win32') {
|
||||
fixture = fixture.replace(/\n/g, '\n\r');
|
||||
}
|
||||
@@ -515,7 +501,7 @@ test.describe('Search Tests', () => {
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
// Move cursor forward 1 time to create a null character, as opposed to regular whitespace
|
||||
await ctx.proxy.write('\x1b[CHi Hi');
|
||||
await ctx.proxy.write('\\x1b[CHi Hi');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('h', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';
|
||||
|
||||
import { spawn } from 'node-pty';
|
||||
import { Utf8ToUtf32, stringFromCodePoint } from 'common/primitives/input/TextDecoder';
|
||||
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
|
||||
import { Terminal } from 'browser/public/Terminal';
|
||||
import { SerializeAddon } from 'SerializeAddon';
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
import type { IBuffer, IBufferCell, IBufferRange, ITerminalAddon, Terminal } from '@xterm/xterm';
|
||||
import type { IHTMLSerializeOptions, SerializeAddon as ISerializeApi, ISerializeOptions, ISerializeRange } from '@xterm/addon-serialize';
|
||||
import { IColor } from 'common/primitives/Types';
|
||||
import { IAttributeData } from 'common/primitives/buffer/Types';
|
||||
import { IColor } from 'common/Types';
|
||||
import { IAttributeData } from 'common/buffer/Types';
|
||||
import { DEFAULT_ANSI_COLORS } from 'browser/Types';
|
||||
import { UnderlineStyle } from 'common/primitives/buffer/Constants';
|
||||
import { UnderlineStyle } from 'common/buffer/Constants';
|
||||
|
||||
function constrain(value: number, low: number, high: number): number {
|
||||
return Math.max(low, Math.min(value, high));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';
|
||||
|
||||
import { spawn } from 'node-pty';
|
||||
import { Utf8ToUtf32, stringFromCodePoint } from 'common/primitives/input/TextDecoder';
|
||||
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
|
||||
import { CoreBrowserTerminal } from 'browser/CoreBrowserTerminal';
|
||||
import { UnicodeGraphemeProvider } from 'UnicodeGraphemeProvider';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* UnicodeVersionProvider for V15 with grapheme cluster handling.
|
||||
* UnicodeVersionProvider for V15 with grapeme cluster handleing.
|
||||
*/
|
||||
|
||||
import type { Terminal, ITerminalAddon, IUnicodeHandling } from '@xterm/xterm';
|
||||
|
||||
@@ -57,8 +57,7 @@ function isUrl(urlString: string): boolean {
|
||||
|
||||
export class LinkComputer {
|
||||
public static computeLink(y: number, regex: RegExp, terminal: Terminal, activate: (event: MouseEvent, uri: string) => void): ILink[] {
|
||||
const flags = regex.flags.includes('g') ? regex.flags : `${regex.flags}g`;
|
||||
const rex = new RegExp(regex.source, flags);
|
||||
const rex = new RegExp(regex.source, (regex.flags || '') + 'g');
|
||||
|
||||
const [lines, startLineIndex] = LinkComputer._getWindowedLineStrings(y - 1, terminal);
|
||||
const line = lines.join('');
|
||||
|
||||
@@ -7,13 +7,13 @@ import type { Terminal, ITerminalAddon, IDisposable } from '@xterm/xterm';
|
||||
import type { WebLinksAddon as IWebLinksApi } from '@xterm/addon-web-links';
|
||||
import { ILinkProviderOptions, WebLinkProvider } from './WebLinkProvider';
|
||||
|
||||
// consider everything starting with http:// or https://
|
||||
// consider everthing starting with http:// or https://
|
||||
// up to first whitespace, `"` or `'` as url
|
||||
// NOTE: The repeated end clause is needed to not match a dangling `:`
|
||||
// resembling the old (...)*([^:"\'\\s]) final path clause
|
||||
// additionally exclude early + final:
|
||||
// - unsafe from rfc3986: !*'()
|
||||
// - unsafe chars from rfc1738: {}|\^~[]` (minus [] for ipv6 addresses, also allow ~)
|
||||
// - unsafe chars from rfc1738: {}|\^~[]` (minus [] as we need them for ipv6 adresses, also allow ~)
|
||||
// also exclude as finals:
|
||||
// - final interpunction like ,.!?
|
||||
// - any sort of brackets <>()[]{} (not spec conform, but often used to enclose urls)
|
||||
|
||||
@@ -23,7 +23,7 @@ See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/addon-
|
||||
|
||||
### Handling Context Loss
|
||||
|
||||
The browser may drop WebGL contexts for various reasons like OOM or after the system has been suspended. There is an API exposed that fires the `webglcontextlost` event on the canvas so embedders can handle it however they wish. An easy, but suboptimal way, to handle this is by disposing of WebglAddon when the event fires:
|
||||
The browser may drop WebGL contexts for various reasons like OOM or after the system has been suspended. There is an API exposed that fires the `webglcontextlost` event fired on the canvas so embedders can handle it however they wish. An easy, but suboptimal way, to handle this is by disposing of WebglAddon when the event fires:
|
||||
|
||||
```ts
|
||||
const terminal = new Terminal();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
||||
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||
import { ReadonlyColorSet } from 'browser/Types';
|
||||
import { Attributes, BgFlags, ExtFlags, FgFlags, NULL_CELL_CODE, UnderlineStyle } from 'common/primitives/buffer/Constants';
|
||||
import { Attributes, BgFlags, ExtFlags, FgFlags, NULL_CELL_CODE, UnderlineStyle } from 'common/buffer/Constants';
|
||||
import { IDecorationService, IOptionsService } from 'common/services/Services';
|
||||
import { ICellData } from 'common/primitives/buffer/Types';
|
||||
import { ICellData } from 'common/buffer/Types';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { rgba } from 'common/primitives/Color';
|
||||
import { rgba } from 'common/Color';
|
||||
import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
|
||||
import { blockPatternCodepoints } from './customGlyphs/CustomGlyphDefinitions';
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import { assert } from 'chai';
|
||||
import { configEquals } from './CharAtlasUtils';
|
||||
import { ICharAtlasConfig } from './Types';
|
||||
import { NULL_COLOR } from 'common/primitives/Color';
|
||||
import { IColor } from 'common/primitives/Types';
|
||||
import { NULL_COLOR } from 'common/Color';
|
||||
import { IColor } from 'common/Types';
|
||||
|
||||
function createTestConfig(overrides: Partial<ICharAtlasConfig> = {}): ICharAtlasConfig {
|
||||
const color: IColor = { css: '#ffffff', rgba: 0xffffffff };
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
import { ICharAtlasConfig } from './Types';
|
||||
import { Attributes } from 'common/primitives/buffer/Constants';
|
||||
import { Attributes } from 'common/buffer/Constants';
|
||||
import { ITerminalOptions } from '@xterm/xterm';
|
||||
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
|
||||
import { NULL_COLOR } from 'common/primitives/Color';
|
||||
import { NULL_COLOR } from 'common/Color';
|
||||
|
||||
export function generateConfig(deviceCellWidth: number, deviceCellHeight: number, deviceCharWidth: number, deviceCharHeight: number, options: Required<ITerminalOptions>, colors: ReadonlyColorSet, devicePixelRatio: number, deviceMaxTextureSize: number, customGlyphs: boolean = true): ICharAtlasConfig {
|
||||
// null out some fields that don't matter
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { isFirefox, isLegacyEdge } from 'common/primitives/Platform';
|
||||
import { isFirefox, isLegacyEdge } from 'common/Platform';
|
||||
|
||||
export const DIM_OPACITY = 0.5;
|
||||
// The text baseline is set conditionally by browser. Using 'ideographic' for Firefox or Legacy Edge
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { toDisposable, IDisposable } from 'common/primitives/Lifecycle';
|
||||
import { toDisposable, IDisposable } from 'common/Lifecycle';
|
||||
|
||||
export function observeDevicePixelDimensions(element: HTMLElement, parentWindow: Window & typeof globalThis, callback: (deviceWidth: number, deviceHeight: number) => void): IDisposable {
|
||||
// Observe any resizes to the element and extract the actual pixel size of the element if the
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
import { TextureAtlas } from './TextureAtlas';
|
||||
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||
import { NULL_CELL_CODE } from 'common/primitives/buffer/Constants';
|
||||
import { Disposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { NULL_CELL_CODE } from 'common/buffer/Constants';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject, type IRasterizedGlyph, type ITextureAtlas } from './Types';
|
||||
import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
|
||||
@@ -220,7 +220,7 @@ export class GlyphRenderer extends Disposable {
|
||||
public updateCell(x: number, y: number, code: number, bg: number, fg: number, ext: number, chars: string, width: number, lastBg: number): void {
|
||||
// Since this function is called for every cell (`rows*cols`), it must be very optimized. It
|
||||
// should not instantiate any variables unless a new glyph is drawn to the cache where the
|
||||
// slight slowdown is acceptable for the developer ergonomics provided as it's a one-off for
|
||||
// slight slowdown is acceptable for the developer ergonomics provided as it's a once of for
|
||||
// each glyph.
|
||||
this._updateCell(this._vertices.attributes, x, y, code, bg, fg, ext, chars, width, lastBg);
|
||||
}
|
||||
@@ -389,9 +389,8 @@ export class GlyphRenderer extends Disposable {
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[i].texture);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, atlas.pages[i].canvas);
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
this._atlasTextures[i].version = atlas.pages[i].version;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||
import { IThemeService } from 'browser/services/Services';
|
||||
import { ReadonlyColorSet } from 'browser/Types';
|
||||
import { Attributes, FgFlags } from 'common/primitives/buffer/Constants';
|
||||
import { Disposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { IColor } from 'common/primitives/Types';
|
||||
import { Attributes, FgFlags } from 'common/buffer/Constants';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { IColor } from 'common/Types';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { RenderModelConstants } from './RenderModel';
|
||||
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
|
||||
|
||||
@@ -8,14 +8,14 @@ import { DIM_OPACITY, TEXT_BASELINE } from './Constants';
|
||||
import { tryDrawCustomGlyph } from './customGlyphs/CustomGlyphRasterizer';
|
||||
import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from './Types';
|
||||
import { NULL_COLOR, channels, color, rgba } from 'common/primitives/Color';
|
||||
import { FourKeyMap } from 'common/primitives/MultiKeyMap';
|
||||
import { IdleTaskQueue } from 'common/primitives/TaskQueue';
|
||||
import { IColor } from 'common/primitives/Types';
|
||||
import { AttributeData } from 'common/primitives/buffer/AttributeData';
|
||||
import { Attributes, DEFAULT_COLOR, DEFAULT_EXT, UnderlineStyle } from 'common/primitives/buffer/Constants';
|
||||
import { NULL_COLOR, channels, color, rgba } from 'common/Color';
|
||||
import { FourKeyMap } from 'common/MultiKeyMap';
|
||||
import { IdleTaskQueue } from 'common/TaskQueue';
|
||||
import { IColor } from 'common/Types';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { Attributes, DEFAULT_COLOR, DEFAULT_EXT, UnderlineStyle } from 'common/buffer/Constants';
|
||||
import { ILogService, IUnicodeService } from 'common/services/Services';
|
||||
import { Emitter } from 'common/primitives/Event';
|
||||
import { Emitter } from 'common/Event';
|
||||
|
||||
/**
|
||||
* A shared object which is used to draw nothing for a particular cell.
|
||||
@@ -69,7 +69,7 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
private _overflowSizePage: AtlasPage | undefined;
|
||||
|
||||
private _tmpCanvas: HTMLCanvasElement;
|
||||
// A temporary context that glyphs are drawn to before being transferred to the atlas.
|
||||
// A temporary context that glyphs are drawn to before being transfered to the atlas.
|
||||
private _tmpCtx: CanvasRenderingContext2D;
|
||||
|
||||
private _workBoundingBox: IBoundingBox = { top: 0, left: 0, bottom: 0, right: 0 };
|
||||
@@ -152,7 +152,7 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
}
|
||||
|
||||
private _createNewPage(): AtlasPage {
|
||||
// Try merge the set of the 4 most used pages of the largest size. This is deferred to a
|
||||
// Try merge the set of the 4 most used pages of the largest size. This is is deferred to a
|
||||
// microtask to ensure it does not interrupt textures that will be rendered in the current
|
||||
// animation frame which would result in blank rendered areas. This is actually not that
|
||||
// expensive relative to drawing the glyphs, so there is no need to wait for an idle callback.
|
||||
@@ -191,7 +191,7 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
return newPage;
|
||||
}
|
||||
|
||||
const sortedMergingPagesIndexes = mergingPages.map(e => e.glyphs[0].texturePage).sort((a, b) => a - b);
|
||||
const sortedMergingPagesIndexes = mergingPages.map(e => e.glyphs[0].texturePage).sort((a, b) => a > b ? 1 : -1);
|
||||
const mergedPageIndex = this.pages.length - mergingPages.length;
|
||||
|
||||
// Merge into the new page
|
||||
@@ -1080,33 +1080,17 @@ class AtlasPage {
|
||||
size: number,
|
||||
sourcePages?: AtlasPage[]
|
||||
) {
|
||||
if (sourcePages) {
|
||||
for (const p of sourcePages) {
|
||||
this._glyphs.push(...p.glyphs);
|
||||
this._usedPixels += p._usedPixels;
|
||||
}
|
||||
}
|
||||
this.canvas = createCanvas(document, size, size);
|
||||
// The canvas needs alpha because we use clearColor to convert the background color to alpha.
|
||||
// It might also contain some characters with transparent backgrounds if allowTransparency is
|
||||
// set.
|
||||
this.ctx = throwIfFalsy(this.canvas.getContext('2d', { alpha: true }));
|
||||
if (sourcePages) {
|
||||
if (sourcePages.length === 4) {
|
||||
// optimized for quadmerge
|
||||
this._glyphs = this._glyphs.concat(
|
||||
sourcePages[0].glyphs,
|
||||
sourcePages[1].glyphs,
|
||||
sourcePages[2].glyphs,
|
||||
sourcePages[3].glyphs
|
||||
);
|
||||
this._usedPixels = sourcePages[0]._usedPixels +
|
||||
sourcePages[1]._usedPixels +
|
||||
sourcePages[2]._usedPixels +
|
||||
sourcePages[3]._usedPixels;
|
||||
} else {
|
||||
// fallback for non quadmerges (should never be used)
|
||||
for (let i = 0; i < sourcePages.length; ++i) {
|
||||
this._glyphs = this._glyphs.concat(sourcePages[i].glyphs);
|
||||
this._usedPixels += sourcePages[i]._usedPixels;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import { FontWeight } from '@xterm/xterm';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
||||
import { CursorInactiveStyle, CursorStyle, type IDisposable } from 'common/primitives/Types';
|
||||
import type { IEvent } from 'common/primitives/Event';
|
||||
import { CursorInactiveStyle, CursorStyle, type IDisposable } from 'common/Types';
|
||||
import type { IEvent } from 'common/Event';
|
||||
|
||||
export interface IRenderModel {
|
||||
cells: Uint32Array;
|
||||
|
||||
@@ -7,12 +7,12 @@ import type { ITerminalAddon, Terminal } from '@xterm/xterm';
|
||||
import type { IWebglAddonOptions, WebglAddon as IWebglApi } from '@xterm/addon-webgl';
|
||||
import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
|
||||
import { ITerminal } from 'browser/Types';
|
||||
import { Disposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { getSafariVersion, isSafari } from 'common/primitives/Platform';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { getSafariVersion, isSafari } from 'common/Platform';
|
||||
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
|
||||
import { IWebGL2RenderingContext } from './Types';
|
||||
import { WebglRenderer } from './WebglRenderer';
|
||||
import { Emitter, EventUtils } from 'common/primitives/Event';
|
||||
import { Emitter, EventUtils } from 'common/Event';
|
||||
|
||||
export class WebglAddon extends Disposable implements ITerminalAddon, IWebglApi {
|
||||
private _terminal?: Terminal;
|
||||
|
||||
@@ -10,10 +10,10 @@ import { CursorBlinkStateManager } from './CursorBlinkStateManager';
|
||||
import { observeDevicePixelDimensions } from './DevicePixelObserver';
|
||||
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types';
|
||||
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||
import { CharData, IBufferLine, ICellData } from 'common/primitives/buffer/Types';
|
||||
import { AttributeData } from 'common/primitives/buffer/AttributeData';
|
||||
import { CellData } from 'common/primitives/buffer/CellData';
|
||||
import { Attributes, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/primitives/buffer/Constants';
|
||||
import { CharData, IBufferLine, ICellData } from 'common/buffer/Types';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { Attributes, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
|
||||
import { TextBlinkStateManager } from 'browser/renderer/shared/TextBlinkStateManager';
|
||||
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
@@ -23,9 +23,9 @@ import { COMBINED_CHAR_BIT_MASK, RenderModel, RenderModelConstants } from './Ren
|
||||
import { IWebGL2RenderingContext, type ITextureAtlas } from './Types';
|
||||
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
|
||||
import { IRenderLayer } from './renderLayer/Types';
|
||||
import { Emitter, EventUtils } from 'common/primitives/Event';
|
||||
import { Emitter, EventUtils } from 'common/Event';
|
||||
import { addDisposableListener } from 'browser/Dom';
|
||||
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
|
||||
|
||||
const enum Constants {
|
||||
@@ -456,18 +456,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
|
||||
for (y = start; y <= end; y++) {
|
||||
row = y + terminal.buffer.ydisp;
|
||||
const bufferLine = terminal.buffer.lines.get(row);
|
||||
if (!bufferLine) {
|
||||
this._model.lineLengths[y] = 0;
|
||||
for (x = 0; x < terminal.cols; x++) {
|
||||
j = ((y * terminal.cols) + x) * RenderModelConstants.INDICIES_PER_CELL;
|
||||
modelUpdated = true;
|
||||
this._nullModelCell(x, y, j, 0, 0, 0);
|
||||
}
|
||||
this._setRowBlinkState(y, false);
|
||||
continue;
|
||||
}
|
||||
line = bufferLine;
|
||||
line = terminal.buffer.lines.get(row)!;
|
||||
let rowHasBlinkingCells = false;
|
||||
this._model.lineLengths[y] = 0;
|
||||
isCursorRow = cursorY === row;
|
||||
@@ -598,9 +587,13 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
// Null out non-first cells
|
||||
for (x++; x <= lastCharX; x++) {
|
||||
j = ((y * terminal.cols) + x) * RenderModelConstants.INDICIES_PER_CELL;
|
||||
this._glyphRenderer.value!.updateCell(x, y, NULL_CELL_CODE, 0, 0, 0, NULL_CELL_CHAR, 0, 0);
|
||||
this._model.cells[j] = NULL_CELL_CODE;
|
||||
// Don't re-resolve the cell color since multi-colored ligature backgrounds are not
|
||||
// supported
|
||||
this._nullModelCell(x, y, j, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext);
|
||||
this._model.cells[j + RenderModelConstants.BG_OFFSET] = this._cellColorResolver.result.bg;
|
||||
this._model.cells[j + RenderModelConstants.FG_OFFSET] = this._cellColorResolver.result.fg;
|
||||
this._model.cells[j + RenderModelConstants.EXT_OFFSET] = this._cellColorResolver.result.ext;
|
||||
}
|
||||
x--; // Go back to the previous update cell for next iteration
|
||||
}
|
||||
@@ -614,14 +607,6 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
this._updateTextBlinkState();
|
||||
}
|
||||
|
||||
private _nullModelCell(x: number, y: number, cellIndex: number, bg: number, fg: number, ext: number): void {
|
||||
this._glyphRenderer.value!.updateCell(x, y, NULL_CELL_CODE, bg, fg, ext, NULL_CELL_CHAR, 0, 0);
|
||||
this._model.cells[cellIndex] = NULL_CELL_CODE;
|
||||
this._model.cells[cellIndex + RenderModelConstants.BG_OFFSET] = bg;
|
||||
this._model.cells[cellIndex + RenderModelConstants.FG_OFFSET] = fg;
|
||||
this._model.cells[cellIndex + RenderModelConstants.EXT_OFFSET] = ext;
|
||||
}
|
||||
|
||||
private _resetBlinkingRowState(): void {
|
||||
this._rowHasBlinkingCells = new Array(this._terminal.rows).fill(false);
|
||||
this._rowHasBlinkingCellsCount = 0;
|
||||
|
||||
@@ -7,8 +7,8 @@ import { ReadonlyColorSet } from 'browser/Types';
|
||||
import { acquireTextureAtlas } from '../CharAtlasCache';
|
||||
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||
import { Disposable, toDisposable } from 'common/primitives/Lifecycle';
|
||||
import { CellData } from 'common/primitives/buffer/CellData';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { IOptionsService } from 'common/services/Services';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { IRenderLayer } from './Types';
|
||||
|
||||
+2
-5
@@ -19,17 +19,14 @@ for (const addon of addons) {
|
||||
// Demo job - This requires the others to be built so it's not included when building all
|
||||
// jobs.push(createJob('demo-client', [`--demo-client`]));
|
||||
|
||||
const codes = await Promise.all(jobs.map(job => {
|
||||
await Promise.all(jobs.map((job, i) => {
|
||||
return new Promise(r => {
|
||||
job.cp.on('exit', code => {
|
||||
log(`Finished \x1b[32m${job.name}\x1b[0m${code ? ' \x1b[31mwith errors\x1b[0m' : ''}`);
|
||||
r(code ?? 1);
|
||||
r(code);
|
||||
});
|
||||
});
|
||||
}));
|
||||
if (codes.some(code => code !== 0)) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} message
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import { spawnSync } from 'node:child_process';
|
||||
import { basename, dirname, resolve, sep } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
|
||||
const nodeModulesPath = resolve(repoRoot, 'node_modules');
|
||||
const npmExecutable = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
|
||||
@@ -13,7 +13,7 @@ const npmExecutable = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
|
||||
/** @param {string} message */
|
||||
function log(message) {
|
||||
console.info(`[setup-full] ${message}`);
|
||||
console.info(`[setup-fast] ${message}`);
|
||||
}
|
||||
|
||||
/** @param {string[]} args */
|
||||
|
||||
+3
-12
@@ -12,7 +12,7 @@ let argv = process.argv.slice(2);
|
||||
let suiteFilter = undefined;
|
||||
while (argv.some(e => e.startsWith('--suite='))) {
|
||||
const i = argv.findIndex(e => e.startsWith('--suite='));
|
||||
const match = argv[i].match(/--suite=(?<suitename>.+)/);
|
||||
const match = argv[i].match(/--suite=(?<suitename>.+)/)
|
||||
suiteFilter = match?.groups?.suitename ?? undefined;
|
||||
argv.splice(i, 1);
|
||||
}
|
||||
@@ -42,18 +42,12 @@ if (suiteFilter) {
|
||||
configs = configs.filter(e => e.name === suiteFilter);
|
||||
}
|
||||
|
||||
if (suiteFilter && configs.length === 0) {
|
||||
console.error(`Unknown suite: ${suiteFilter}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function npmBinScript(script) {
|
||||
return path.resolve(__dirname, `../node_modules/.bin/` + (process.platform === 'win32' ?
|
||||
`${script}.cmd` : script));
|
||||
}
|
||||
|
||||
async function run() {
|
||||
let exitCode = 0;
|
||||
for (const config of configs) {
|
||||
const command = npmBinScript('playwright');
|
||||
const args = ['test', '-c', config.path, ...argv];
|
||||
@@ -68,13 +62,10 @@ async function run() {
|
||||
|
||||
if (run.error) {
|
||||
console.error(run.error);
|
||||
process.exit(run.status ?? 1);
|
||||
process.exit(run.status ?? -1);
|
||||
}
|
||||
|
||||
if (run.status) {
|
||||
exitCode = run.status;
|
||||
}
|
||||
process.exit(run.status);
|
||||
}
|
||||
process.exit(exitCode);
|
||||
}
|
||||
run();
|
||||
|
||||
@@ -177,7 +177,7 @@ const ENC = {
|
||||
}
|
||||
|
||||
function printMenu() {
|
||||
console.log('\x1b[2J\x1b[HTest mouse reports [Ctrl-C to exit]');
|
||||
console.log('\x1b[2J\x1b\[HTest mouse reports [Ctrl-C to exit]');
|
||||
console.log();
|
||||
console.log(' Selected protocol [Ctrl-A to switch]');
|
||||
const protocols = Object.keys(PROTOCOLS);
|
||||
|
||||
+4
-2
@@ -21,7 +21,7 @@ if (process.argv.length > 2) {
|
||||
flagArgs = args.filter(e => e.startsWith('--'));
|
||||
// ability to inject particular test files via
|
||||
// npm run test [testFileA testFileB ...]
|
||||
const files = args.filter(e => !e.startsWith('--'));
|
||||
files = args.filter(e => !e.startsWith('--'));
|
||||
if (files.length) {
|
||||
testFiles = files;
|
||||
}
|
||||
@@ -39,6 +39,8 @@ if (checkCoverage) {
|
||||
...testFiles,
|
||||
...flagArgs
|
||||
];
|
||||
console.info('executable', executable);
|
||||
console.info('args', args);
|
||||
const run = cp.spawnSync(
|
||||
executable,
|
||||
args,
|
||||
@@ -49,7 +51,7 @@ if (checkCoverage) {
|
||||
stdio: 'inherit'
|
||||
}
|
||||
);
|
||||
process.exit(run.status ?? -1);
|
||||
process.exit(run.status);
|
||||
}
|
||||
|
||||
const run = cp.spawnSync(
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BaseWindow } from './baseWindow';
|
||||
import type { IControlWindow } from '../controlBar';
|
||||
import type { IBufferCell } from '@xterm/xterm';
|
||||
|
||||
// Underline style values from common/primitives/buffer/Constants.ts
|
||||
// Underline style values from common/buffer/Constants.ts
|
||||
const enum UnderlineStyle {
|
||||
NONE = 0,
|
||||
SINGLE = 1,
|
||||
|
||||
@@ -11,33 +11,8 @@ export class WebglWindow extends BaseWindow implements IControlWindow {
|
||||
public readonly label = 'webgl';
|
||||
|
||||
private _textureAtlasContainer!: HTMLElement;
|
||||
private _stressRunning = false;
|
||||
private _stressScrolling: HTMLInputElement | undefined;
|
||||
|
||||
public build(container: HTMLElement): void {
|
||||
const stressDiv = document.createElement('div');
|
||||
const stressStart = document.createElement('button');
|
||||
stressStart.id = 'stress-start';
|
||||
stressStart.textContent = 'atlas stress start';
|
||||
stressStart.addEventListener('click', () => this._stress());
|
||||
stressDiv.appendChild(stressStart);
|
||||
|
||||
const stressStop = document.createElement('button');
|
||||
stressStop.id = 'stress-stop';
|
||||
stressStop.textContent = 'atlas stress stop';
|
||||
stressStop.addEventListener('click', () => this._stressRunning = false);
|
||||
stressDiv.appendChild(stressStop);
|
||||
|
||||
this._stressScrolling = document.createElement('input');
|
||||
this._stressScrolling.type = 'checkbox';
|
||||
this._stressScrolling.id = 'stress-scrolling';
|
||||
stressDiv.appendChild(this._stressScrolling);
|
||||
const stressScrollingLabel = document.createElement('label');
|
||||
stressScrollingLabel.htmlFor = 'stress-scrolling';
|
||||
stressScrollingLabel.textContent = 'stress scrolling';
|
||||
stressDiv.appendChild(stressScrollingLabel);
|
||||
container.appendChild(stressDiv);
|
||||
|
||||
const zoomCheckbox = document.createElement('input');
|
||||
zoomCheckbox.type = 'checkbox';
|
||||
zoomCheckbox.id = 'texture-atlas-zoom';
|
||||
@@ -73,33 +48,4 @@ export class WebglWindow extends BaseWindow implements IControlWindow {
|
||||
canvas.style.width = `${canvas.width / dpr}px`;
|
||||
canvas.style.height = `${canvas.height / dpr}px`;
|
||||
}
|
||||
|
||||
private async _stress(): Promise<void> {
|
||||
const TEXT = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
|
||||
if (this._stressRunning) {
|
||||
return;
|
||||
}
|
||||
this._stressRunning = true;
|
||||
const scrolling = !!(this._stressScrolling?.checked);
|
||||
for (let r = 0; r < 256; r += 2) {
|
||||
for (let g = 0; g < 256; g += 2) {
|
||||
let s: string[] = [];
|
||||
for (let b = 0; b < 256; b += 2) {
|
||||
if (!this._stressRunning) {
|
||||
return;
|
||||
}
|
||||
const rbg = `RGB: ${[r, g, b]}`;
|
||||
s.push(`\r\x1b[38;2;${r};${g};${b}m${rbg.padEnd(18, ' ')}${TEXT}`);
|
||||
if (s.length >= 16) {
|
||||
if (scrolling) {
|
||||
await new Promise<void>(r => this._terminal.write(s.join('\r\n') + '\r\n', r));
|
||||
} else {
|
||||
await new Promise<void>(r => this._terminal.write('\x1b[H' + s.join('\r\n'), r));
|
||||
}
|
||||
s = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+36
-5
@@ -6689,6 +6689,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
@@ -6922,6 +6932,27 @@
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
@@ -7047,13 +7078,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz",
|
||||
"integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
|
||||
+3
-6
@@ -11,9 +11,6 @@
|
||||
"workspaces": [
|
||||
"addons/*"
|
||||
],
|
||||
"overrides": {
|
||||
"serialize-javascript": "^7.0.3"
|
||||
},
|
||||
"keywords": [
|
||||
"cli",
|
||||
"command-line",
|
||||
@@ -64,9 +61,9 @@
|
||||
"test-integration-firefox": "node ./bin/test_integration.js --workers=75% \"--project=FirefoxStable\"",
|
||||
"test-integration-webkit": "node ./bin/test_integration.js --workers=75% \"--project=WebKit\"",
|
||||
"test-integration-debug": "node ./bin/test_integration.js --workers=1 --headed --timeout=30000",
|
||||
"benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
|
||||
"benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/*benchmark.js",
|
||||
"benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/*benchmark.js",
|
||||
"benchmark": "xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
|
||||
"benchmark-baseline": "xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/*benchmark.js",
|
||||
"benchmark-eval": "xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/*benchmark.js",
|
||||
"clean": "rm -rf lib out addons/*/lib addons/*/out",
|
||||
"vtfeatures": "node bin/extract_vtfeatures.js src/*/*.ts src/*/*/*.ts src/*.ts addons/**/src/*.ts",
|
||||
"prepackage": "npm run build",
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
import * as Strings from './LocalizableStrings';
|
||||
import { ITerminal, IRenderDebouncer } from './Types';
|
||||
import { TimeBasedDebouncer } from './TimeBasedDebouncer';
|
||||
import { Disposable, toDisposable } from '../common/primitives/Lifecycle';
|
||||
import { Disposable, toDisposable } from '../common/Lifecycle';
|
||||
import { ICoreBrowserService, IRenderService } from './services/Services';
|
||||
import { IBuffer } from '../common/primitives/buffer/Types';
|
||||
import { IBuffer } from '../common/buffer/Types';
|
||||
import { IInstantiationService } from '../common/services/Services';
|
||||
import { addDisposableListener } from './Dom';
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import { IColorContrastCache } from './Types';
|
||||
import { IColor } from '../common/primitives/Types';
|
||||
import { TwoKeyMap } from '../common/primitives/MultiKeyMap';
|
||||
import { IColor } from '../common/Types';
|
||||
import { TwoKeyMap } from '../common/MultiKeyMap';
|
||||
|
||||
export class ColorContrastCache implements IColorContrastCache {
|
||||
private _color: TwoKeyMap</* bg */number, /* fg */number, IColor | null> = new TwoKeyMap();
|
||||
|
||||
@@ -43,23 +43,22 @@ import { SelectionService } from './services/SelectionService';
|
||||
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IKeyboardService, ILinkProviderService, IMouseCoordsService, IMouseService, IRenderService, ISelectionService, IThemeService } from './services/Services';
|
||||
import { ThemeService } from './services/ThemeService';
|
||||
import { KeyboardService } from './services/KeyboardService';
|
||||
import { channels, color, rgb } from '../common/primitives/Color';
|
||||
import { channels, color, rgb } from '../common/Color';
|
||||
import { CoreTerminal } from '../common/CoreTerminal';
|
||||
import * as Browser from '../common/primitives/Platform';
|
||||
import { ColorRequestType, IColorEvent, KeyboardResultType, SpecialColorIndex } from '../common/primitives/Types';
|
||||
import { ITerminalOptions } from '../common/Types';
|
||||
import { DEFAULT_ATTR_DATA } from '../common/primitives/buffer/BufferLine';
|
||||
import { IBuffer } from '../common/primitives/buffer/Types';
|
||||
import { C0, C1ESCAPED } from '../common/primitives/data/EscapeSequences';
|
||||
import { toRgbString } from '../common/primitives/input/XParseColor';
|
||||
import * as Browser from '../common/Platform';
|
||||
import { ColorRequestType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from '../common/Types';
|
||||
import { DEFAULT_ATTR_DATA } from '../common/buffer/BufferLine';
|
||||
import { IBuffer } from '../common/buffer/Types';
|
||||
import { C0, C1ESCAPED } from '../common/data/EscapeSequences';
|
||||
import { toRgbString } from '../common/input/XParseColor';
|
||||
import { DecorationService } from '../common/services/DecorationService';
|
||||
import { IDecorationService } from '../common/services/Services';
|
||||
import { WindowsOptionsReportType } from '../common/InputHandler';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { Linkifier } from './Linkifier';
|
||||
import { Emitter, EventUtils, type IEvent } from '../common/primitives/Event';
|
||||
import { Emitter, EventUtils, type IEvent } from '../common/Event';
|
||||
import { addDisposableListener } from './Dom';
|
||||
import { MutableDisposable, toDisposable } from '../common/primitives/Lifecycle';
|
||||
import { MutableDisposable, toDisposable } from '../common/Lifecycle';
|
||||
|
||||
export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
public textarea: HTMLTextAreaElement | undefined;
|
||||
@@ -506,7 +505,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
this.textarea,
|
||||
parent.ownerDocument.defaultView ?? window,
|
||||
// Force unsafe null in node.js environment for tests
|
||||
this._document ?? ((typeof window !== 'undefined') ? window.document : null as any)
|
||||
this._document ?? (typeof window !== 'undefined') ? window.document : null as any
|
||||
));
|
||||
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
|
||||
|
||||
@@ -1073,6 +1072,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
* Clear the entire buffer, making the prompt line the new first line.
|
||||
*/
|
||||
public clear(): void {
|
||||
if (this.buffer.ybase === 0 && this.buffer.y === 0) {
|
||||
// Don't clear if it's already clear
|
||||
return;
|
||||
}
|
||||
this.buffer.clearAllMarkers();
|
||||
this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
|
||||
this.buffer.lines.length = 1;
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@
|
||||
* Minimal DOM helpers for xterm.js browser code.
|
||||
*/
|
||||
|
||||
import { IntervalTimer } from '../common/primitives/Async';
|
||||
import { IDisposable } from '../common/primitives/Lifecycle';
|
||||
import { IntervalTimer } from '../common/Async';
|
||||
import { IDisposable } from '../common/Lifecycle';
|
||||
|
||||
export function getWindow(e: Node | UIEvent | undefined | null): Window {
|
||||
const candidateNode = e as Node | undefined | null;
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
*/
|
||||
|
||||
import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from './Types';
|
||||
import { Disposable, dispose, toDisposable } from '../common/primitives/Lifecycle';
|
||||
import { IDisposable } from '../common/primitives/Types';
|
||||
import { Disposable, dispose, toDisposable } from '../common/Lifecycle';
|
||||
import { IDisposable } from '../common/Types';
|
||||
import { IBufferService } from '../common/services/Services';
|
||||
import { ILinkProviderService, IMouseCoordsService, IRenderService } from './services/Services';
|
||||
import { Emitter } from '../common/primitives/Event';
|
||||
import { Emitter } from '../common/Event';
|
||||
import { addDisposableListener } from './Dom';
|
||||
|
||||
export class Linkifier extends Disposable implements ILinkifier2 {
|
||||
|
||||
@@ -8,8 +8,8 @@ import { OscLinkProvider } from './OscLinkProvider';
|
||||
import { ILink } from './Types';
|
||||
import { createCellData, MockBufferService, MockOptionsService } from '../common/TestUtils.test';
|
||||
import { IBufferService, IOscLinkService } from '../common/services/Services';
|
||||
import { IOscLinkData } from '../common/primitives/Types';
|
||||
import { IBufferLine } from '../common/primitives/buffer/Types';
|
||||
import { IOscLinkData } from '../common/Types';
|
||||
import { IBufferLine } from '../common/buffer/Types';
|
||||
|
||||
class TestOscLinkService implements IOscLinkService {
|
||||
public serviceBrand: any;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { IBufferRange, ILink } from './Types';
|
||||
import { ILinkProvider } from './services/Services';
|
||||
import { CellData } from '../common/primitives/buffer/CellData';
|
||||
import { IBufferLine } from '../common/primitives/buffer/Types';
|
||||
import { CellData } from '../common/buffer/CellData';
|
||||
import { IBufferLine } from '../common/buffer/Types';
|
||||
import { IBufferService, IOptionsService, IOscLinkService } from '../common/services/Services';
|
||||
|
||||
export class OscLinkProvider implements ILinkProvider {
|
||||
|
||||
@@ -23,7 +23,7 @@ export class RenderDebouncer implements IRenderDebouncerWithCallback {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this._animationFrame !== undefined) {
|
||||
if (this._animationFrame) {
|
||||
this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame);
|
||||
this._animationFrame = undefined;
|
||||
}
|
||||
@@ -31,7 +31,9 @@ export class RenderDebouncer implements IRenderDebouncerWithCallback {
|
||||
|
||||
public addRefreshCallback(callback: FrameRequestCallback): number {
|
||||
this._refreshCallbacks.push(callback);
|
||||
this._animationFrame ??= this._coreBrowserService.window.requestAnimationFrame(() => this._innerRefresh());
|
||||
if (!this._animationFrame) {
|
||||
this._animationFrame = this._coreBrowserService.window.requestAnimationFrame(() => this._innerRefresh());
|
||||
}
|
||||
return this._animationFrame;
|
||||
}
|
||||
|
||||
@@ -44,7 +46,7 @@ export class RenderDebouncer implements IRenderDebouncerWithCallback {
|
||||
this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;
|
||||
this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;
|
||||
|
||||
if (this._animationFrame !== undefined) {
|
||||
if (this._animationFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
import { MockCompositionHelper, MockRenderer, MockViewport, TestTerminal } from './TestUtils.test';
|
||||
import type { IBrowser } from './Types';
|
||||
import { assert } from 'chai';
|
||||
import { DEFAULT_ATTR_DATA } from '../common/primitives/buffer/BufferLine';
|
||||
import { CellData } from '../common/primitives/buffer/CellData';
|
||||
import { DEFAULT_ATTR_DATA } from '../common/buffer/BufferLine';
|
||||
import { CellData } from '../common/buffer/CellData';
|
||||
import { MockUnicodeService, createCellData } from '../common/TestUtils.test';
|
||||
import { IMarker } from '../common/primitives/buffer/Types';
|
||||
import { IMarker } from '../common/buffer/Types';
|
||||
|
||||
const INIT_COLS = 80;
|
||||
const INIT_ROWS = 24;
|
||||
|
||||
@@ -7,20 +7,19 @@ import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration, I
|
||||
import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService, IThemeService } from './services/Services';
|
||||
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from './renderer/shared/Types';
|
||||
import { IColorSet, ITerminal, ILinkifier2, IBrowser, IViewport, ICompositionHelper, CharacterJoinerHandler, IBufferRange, ReadonlyColorSet, IBufferElementProvider } from './Types';
|
||||
import { IAttributeData, IBuffer, IBufferLine, IBufferSet, ICellData } from '../common/primitives/buffer/Types';
|
||||
import { ICircularList } from '../common/primitives/CircularList';
|
||||
import { XtermListener, ICharset, ColorIndex } from '../common/primitives/Types';
|
||||
import { ITerminalOptions } from '../common/Types';
|
||||
import { Buffer } from '../common/primitives/buffer/Buffer';
|
||||
import * as Browser from '../common/primitives/Platform';
|
||||
import { IAttributeData, IBuffer, IBufferLine, IBufferSet, ICellData } from '../common/buffer/Types';
|
||||
import { ICircularList } from '../common/CircularList';
|
||||
import { XtermListener, ICharset, ITerminalOptions, ColorIndex } from '../common/Types';
|
||||
import { Buffer } from '../common/buffer/Buffer';
|
||||
import * as Browser from '../common/Platform';
|
||||
import { CoreBrowserTerminal } from './CoreBrowserTerminal';
|
||||
import { IUnicodeService, IOptionsService, ICoreService, IMouseStateService } from '../common/services/Services';
|
||||
import { IFunctionIdentifier, IParams } from '../common/primitives/parser/Types';
|
||||
import { AttributeData } from '../common/primitives/buffer/AttributeData';
|
||||
import { IFunctionIdentifier, IParams } from '../common/parser/Types';
|
||||
import { AttributeData } from '../common/buffer/AttributeData';
|
||||
import { ISelectionRedrawRequestEvent, ISelectionRequestScrollLinesEvent } from './selection/Types';
|
||||
import { css } from '../common/primitives/Color';
|
||||
import { css } from '../common/Color';
|
||||
import { createRenderDimensions } from './renderer/shared/RendererUtils';
|
||||
import { Emitter, type IEvent } from '../common/primitives/Event';
|
||||
import { Emitter, type IEvent } from '../common/Event';
|
||||
|
||||
export class TestTerminal extends CoreBrowserTerminal {
|
||||
public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; }
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IRenderDebouncer } from './Types';
|
||||
|
||||
const RENDER_DEBOUNCE_THRESHOLD_MS = 1000; // 1 Second
|
||||
|
||||
import { IRenderDebouncer } from './Types';
|
||||
|
||||
/**
|
||||
* Debounces calls to update screen readers to update at most once configurable interval of time.
|
||||
*/
|
||||
@@ -31,9 +31,7 @@ export class TimeBasedDebouncer implements IRenderDebouncer {
|
||||
public dispose(): void {
|
||||
if (this._refreshTimeoutID) {
|
||||
clearTimeout(this._refreshTimeoutID);
|
||||
this._refreshTimeoutID = undefined;
|
||||
}
|
||||
this._additionalRefreshRequested = false;
|
||||
}
|
||||
|
||||
public refresh(rowStart: number | undefined, rowEnd: number | undefined, rowCount: number): void {
|
||||
@@ -50,11 +48,6 @@ export class TimeBasedDebouncer implements IRenderDebouncer {
|
||||
const refreshRequestTime: number = performance.now();
|
||||
if (refreshRequestTime - this._lastRefreshMs >= this._debounceThresholdMS) {
|
||||
// Enough time has elapsed since the last refresh; refresh immediately
|
||||
if (this._refreshTimeoutID !== undefined) {
|
||||
clearTimeout(this._refreshTimeoutID);
|
||||
this._refreshTimeoutID = undefined;
|
||||
this._additionalRefreshRequested = false;
|
||||
}
|
||||
this._lastRefreshMs = refreshRequestTime;
|
||||
this._innerRefresh();
|
||||
} else if (!this._additionalRefreshRequested) {
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IColor } from '../common/primitives/Types';
|
||||
import { ITerminalOptions } from '../common/Types';
|
||||
import { CharData, IBuffer } from '../common/primitives/buffer/Types';
|
||||
import { IColor, ITerminalOptions } from '../common/Types';
|
||||
import { CharData, IBuffer } from '../common/buffer/Types';
|
||||
import { ICoreTerminal } from '../common/CoreTerminal';
|
||||
import { IDisposable, IRenderDimensions as IRenderDimensionsApi, Terminal as ITerminalApi } from '@xterm/xterm';
|
||||
import { channels, css } from '../common/primitives/Color';
|
||||
import type { IEvent } from '../common/primitives/Event';
|
||||
import { channels, css } from '../common/Color';
|
||||
import type { IEvent } from '../common/Event';
|
||||
|
||||
/**
|
||||
* A portion of the public API that are implemented identially internally and simply passed through.
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
import { ICoreBrowserService, IRenderService, IThemeService } from './services/Services';
|
||||
import { ViewportConstants } from './shared/Constants';
|
||||
import { Disposable, toDisposable } from '../common/primitives/Lifecycle';
|
||||
import { Disposable, toDisposable } from '../common/Lifecycle';
|
||||
import { IBufferService, ICoreService, IMouseStateService, IOptionsService } from '../common/services/Services';
|
||||
import { CoreMouseEventType } from '../common/primitives/Types';
|
||||
import { CoreMouseEventType } from '../common/Types';
|
||||
import { scheduleAtNextAnimationFrame } from './Dom';
|
||||
import { SmoothScrollableElement } from './scrollable/scrollableElement';
|
||||
import type { IScrollableElementChangeOptions } from './scrollable/scrollableElementOptions';
|
||||
import { Emitter, EventUtils } from '../common/primitives/Event';
|
||||
import { Emitter, EventUtils } from '../common/Event';
|
||||
import { Scrollable, ScrollbarVisibility, type IScrollEvent } from './scrollable/scrollable';
|
||||
|
||||
export class Viewport extends Disposable {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ICoreBrowserService, IRenderService } from '../services/Services';
|
||||
import { Disposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { Disposable, toDisposable } from '../../common/Lifecycle';
|
||||
import { IBufferService, IDecorationService, IInternalDecoration } from '../../common/services/Services';
|
||||
|
||||
export class BufferDecorationRenderer extends Disposable {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { ColorZoneStore, IColorZone, IColorZoneStore } from './ColorZoneStore';
|
||||
import { ICoreBrowserService, IRenderService, IThemeService } from '../services/Services';
|
||||
import { Disposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { Disposable, toDisposable } from '../../common/Lifecycle';
|
||||
import { IBufferService, IDecorationService, IOptionsService } from '../../common/services/Services';
|
||||
|
||||
const enum Constants {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { IRenderService } from '../services/Services';
|
||||
import { IBufferService, ICoreService, IOptionsService } from '../../common/services/Services';
|
||||
import { C0 } from '../../common/primitives/data/EscapeSequences';
|
||||
import { C0 } from '../../common/data/EscapeSequences';
|
||||
|
||||
interface IPosition {
|
||||
start: number;
|
||||
|
||||
@@ -37,6 +37,10 @@ export function getCoords(window: Pick<Window, 'getComputedStyle'>, event: Pick<
|
||||
}
|
||||
|
||||
const coords = getCoordsRelativeToElement(window, event, element);
|
||||
if (!coords) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
coords[0] = Math.ceil((coords[0] + (isSelection ? cssCellWidth / 2 : 0)) / cssCellWidth);
|
||||
coords[1] = Math.ceil(coords[1] / cssCellHeight);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { C0 } from '../../common/primitives/data/EscapeSequences';
|
||||
import { C0 } from '../../common/data/EscapeSequences';
|
||||
import { IBufferService } from '../../common/services/Services';
|
||||
|
||||
const enum Direction {
|
||||
@@ -156,7 +156,7 @@ function wrappedRowsForRow(currentRow: number, bufferService: IBufferService): n
|
||||
*/
|
||||
function horizontalDirection(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): Direction {
|
||||
let startRow;
|
||||
if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length > 0) {
|
||||
if (moveToRequestedRow(targetX, targetY, bufferService, applicationCursor).length > 0) {
|
||||
startRow = targetY - wrappedRowsForRow(targetY, bufferService);
|
||||
} else {
|
||||
startRow = startY;
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
import * as Strings from '../LocalizableStrings';
|
||||
import { CoreBrowserTerminal as TerminalCore } from '../CoreBrowserTerminal';
|
||||
import { IBufferRange, ITerminal } from '../Types';
|
||||
import { Disposable } from '../../common/primitives/Lifecycle';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
import { ITerminalOptions } from '../../common/Types';
|
||||
import { AddonManager } from '../../common/public/AddonManager';
|
||||
import { BufferNamespaceApi } from '../../common/public/BufferNamespaceApi';
|
||||
import { ParserApi } from '../../common/public/ParserApi';
|
||||
import { UnicodeApi } from '../../common/public/UnicodeApi';
|
||||
import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, IRenderDimensions, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm';
|
||||
import type { IEvent } from '../../common/primitives/Event';
|
||||
import type { IEvent } from '../../common/Event';
|
||||
|
||||
/**
|
||||
* The set of options that only have an effect when set in the Terminal constructor.
|
||||
|
||||
@@ -12,10 +12,10 @@ import { TextBlinkStateManager } from '../shared/TextBlinkStateManager';
|
||||
import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderModel } from '../shared/Types';
|
||||
import { ICharSizeService, ICoreBrowserService, IThemeService } from '../../services/Services';
|
||||
import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from '../../Types';
|
||||
import { color } from '../../../common/primitives/Color';
|
||||
import { Disposable, toDisposable } from '../../../common/primitives/Lifecycle';
|
||||
import { color } from '../../../common/Color';
|
||||
import { Disposable, toDisposable } from '../../../common/Lifecycle';
|
||||
import { IBufferService, ICoreService, IInstantiationService, IOptionsService } from '../../../common/services/Services';
|
||||
import { Emitter } from '../../../common/primitives/Event';
|
||||
import { Emitter } from '../../../common/Event';
|
||||
import { addDisposableListener } from '../../Dom';
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ let nextTerminalId = 1;
|
||||
|
||||
/**
|
||||
* The standard renderer and fallback for when the webgl addon is slow. This is not meant to be
|
||||
* particularly fast and will even lack some features such as custom glyphs, hoever this is more
|
||||
* particularly fast and will even lack some features such as custom glyphs, however this is more
|
||||
* reliable as webgl may not work on some machines.
|
||||
*/
|
||||
export class DomRenderer extends Disposable implements IRenderer {
|
||||
@@ -430,7 +430,7 @@ export class DomRenderer extends Disposable implements IRenderer {
|
||||
documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._bufferService.cols, middleRowsCount));
|
||||
// Draw final row
|
||||
if (viewportCappedStartRow !== viewportCappedEndRow) {
|
||||
// Only draw viewportEndRow if it's not the same as viewporttartRow
|
||||
// Only draw viewportEndRow if it's not the same as viewportStartRow
|
||||
const finalEndCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;
|
||||
documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, finalEndCol));
|
||||
}
|
||||
@@ -536,14 +536,9 @@ export class DomRenderer extends Disposable implements IRenderer {
|
||||
for (let y = start; y <= end; y++) {
|
||||
const row = y + buffer.ydisp;
|
||||
const rowElement = this._rowElements[y];
|
||||
if (!rowElement) {
|
||||
continue;
|
||||
}
|
||||
const lineData = buffer.lines.get(row);
|
||||
if (!lineData) {
|
||||
rowElement.replaceChildren();
|
||||
this._setRowBlinkState(y, false);
|
||||
continue;
|
||||
if (!rowElement || !lineData) {
|
||||
break;
|
||||
}
|
||||
rowElement.replaceChildren(
|
||||
...this._rowFactory.createRow(
|
||||
@@ -615,14 +610,9 @@ export class DomRenderer extends Disposable implements IRenderer {
|
||||
for (let i = y; i <= y2; ++i) {
|
||||
const row = i + buffer.ydisp;
|
||||
const rowElement = this._rowElements[i];
|
||||
if (!rowElement) {
|
||||
continue;
|
||||
}
|
||||
const bufferline = buffer.lines.get(row);
|
||||
if (!bufferline) {
|
||||
rowElement.replaceChildren();
|
||||
this._setRowBlinkState(i, false);
|
||||
continue;
|
||||
if (!rowElement || !bufferline) {
|
||||
break;
|
||||
}
|
||||
rowElement.replaceChildren(
|
||||
...this._rowFactory.createRow(
|
||||
@@ -704,7 +694,7 @@ class CursorBlinkStateManager {
|
||||
}
|
||||
|
||||
private _clearIdleTimer(): void {
|
||||
if (this._idleTimeout !== undefined) {
|
||||
if (this._idleTimeout) {
|
||||
this._coreBrowserService.window.clearTimeout(this._idleTimeout);
|
||||
this._idleTimeout = undefined;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
import jsdom = require('jsdom');
|
||||
import { assert } from 'chai';
|
||||
import { DomRendererRowFactory } from './DomRendererRowFactory';
|
||||
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags, BgFlags, Attributes, UnderlineStyle } from '../../../common/primitives/buffer/Constants';
|
||||
import { BufferLine, DEFAULT_ATTR_DATA } from '../../../common/primitives/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from '../../../common/primitives/buffer/BufferLineStringCache';
|
||||
import { IBufferLine } from '../../../common/primitives/buffer/Types';
|
||||
import { CellData } from '../../../common/primitives/buffer/CellData';
|
||||
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags, BgFlags, Attributes, UnderlineStyle } from '../../../common/buffer/Constants';
|
||||
import { BufferLine, DEFAULT_ATTR_DATA } from '../../../common/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from '../../../common/buffer/BufferLineStringCache';
|
||||
import { IBufferLine } from '../../../common/buffer/Types';
|
||||
import { CellData } from '../../../common/buffer/CellData';
|
||||
import { MockCoreService, MockDecorationService, MockOptionsService, createCellData, NULL_CELL_DATA } from '../../../common/TestUtils.test';
|
||||
import { MockCharacterJoinerService, MockCoreBrowserService, MockThemeService } from '../../TestUtils.test';
|
||||
import { TestWidthCache } from './WidthCache.test';
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IColor } from '../../../common/primitives/Types';
|
||||
import { IBufferLine, ICellData } from '../../../common/primitives/buffer/Types';
|
||||
import { IColor } from '../../../common/Types';
|
||||
import { IBufferLine, ICellData } from '../../../common/buffer/Types';
|
||||
import { INVERTED_DEFAULT_COLOR } from '../shared/Constants';
|
||||
import { WHITESPACE_CELL_CHAR, Attributes } from '../../../common/primitives/buffer/Constants';
|
||||
import { CellData } from '../../../common/primitives/buffer/CellData';
|
||||
import { WHITESPACE_CELL_CHAR, Attributes } from '../../../common/buffer/Constants';
|
||||
import { CellData } from '../../../common/buffer/CellData';
|
||||
import { ICoreService, IDecorationService, IOptionsService } from '../../../common/services/Services';
|
||||
import { channels, color } from '../../../common/primitives/Color';
|
||||
import { channels, color } from '../../../common/Color';
|
||||
import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from '../../services/Services';
|
||||
import { JoinedCellData } from '../../services/CharacterJoinerService';
|
||||
import { treatGlyphAsBackgroundColor } from '../shared/RendererUtils';
|
||||
import { AttributeData } from '../../../common/primitives/buffer/AttributeData';
|
||||
import { AttributeData } from '../../../common/buffer/AttributeData';
|
||||
import { WidthCache } from './WidthCache';
|
||||
import { IColorContrastCache } from '../../Types';
|
||||
|
||||
@@ -380,7 +380,7 @@ export class DomRendererRowFactory {
|
||||
if (!isTop && isInSelection) {
|
||||
// If in the selection, force the element to be above the selection to improve contrast and
|
||||
// support opaque selections. The applies background is not actually needed here as
|
||||
// selection is drawn in a seperate container, the main purpose of this to ensuring minimum
|
||||
// selection is drawn in a separate container; the main purpose of this is to ensure minimum
|
||||
// contrast ratio
|
||||
bgOverride = this._coreBrowserService.isFocused ? colors.selectionBackgroundOpaque : colors.selectionInactiveBackgroundOpaque;
|
||||
bg = bgOverride.rgba >> 8 & 0xFFFFFF;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { throwIfFalsy } from '../shared/RendererUtils';
|
||||
import { IDisposable } from '../../../common/primitives/Types';
|
||||
import { IDisposable } from '../../../common/Types';
|
||||
import { FontWeight } from '../../../common/services/Services';
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { assert } from 'chai';
|
||||
import { TextBlinkStateManager } from './TextBlinkStateManager';
|
||||
import { MockOptionsService } from '../../../common/TestUtils.test';
|
||||
import type { ICoreBrowserService } from '../../services/Services';
|
||||
import { Emitter } from '../../../common/primitives/Event';
|
||||
import { Emitter } from '../../../common/Event';
|
||||
|
||||
class FakeWindow {
|
||||
public nextId = 1;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { ICoreBrowserService } from '../../services/Services';
|
||||
import { Disposable, toDisposable } from '../../../common/primitives/Lifecycle';
|
||||
import { Disposable, toDisposable } from '../../../common/Lifecycle';
|
||||
import { IOptionsService } from '../../../common/services/Services';
|
||||
|
||||
export class TextBlinkStateManager extends Disposable {
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { ITerminal } from '../../Types';
|
||||
import { IDisposable } from '../../../common/primitives/Types';
|
||||
import type { IEvent } from '../../../common/primitives/Event';
|
||||
import { IDisposable } from '../../../common/Types';
|
||||
import type { IEvent } from '../../../common/Event';
|
||||
|
||||
export interface IDimensions {
|
||||
width: number;
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ScrollbarArrow, IScrollbarArrowOptions } from './scrollbarArrow';
|
||||
import { ScrollbarState } from './scrollbarState';
|
||||
import { ScrollbarVisibilityController } from './scrollbarVisibilityController';
|
||||
import { Widget } from './widget';
|
||||
import * as platform from '../../common/primitives/Platform';
|
||||
import * as platform from '../../common/Platform';
|
||||
import { INewScrollPosition, Scrollable, ScrollbarVisibility } from './scrollable';
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from '../Dom';
|
||||
import { DisposableStore, IDisposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { DisposableStore, IDisposable, toDisposable } from '../../common/Lifecycle';
|
||||
|
||||
type PointerMoveCallback = (event: PointerEvent) => void;
|
||||
type OnStopCallback = () => void;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as platform from '../../common/primitives/Platform';
|
||||
import * as platform from '../../common/Platform';
|
||||
|
||||
interface IWindowChainElement {
|
||||
readonly window: WeakRef<Window>;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, IEvent } from '../../common/primitives/Event';
|
||||
import { Disposable, IDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { Emitter, IEvent } from '../../common/Event';
|
||||
import { Disposable, IDisposable } from '../../common/Lifecycle';
|
||||
|
||||
export const enum ScrollbarVisibility {
|
||||
AUTO = 1,
|
||||
|
||||
@@ -11,10 +11,10 @@ import { HorizontalScrollbar } from './horizontalScrollbar';
|
||||
import { IScrollableElementChangeOptions, IScrollableElementCreationOptions, IScrollableElementResolvedOptions } from './scrollableElementOptions';
|
||||
import { VerticalScrollbar } from './verticalScrollbar';
|
||||
import { Widget } from './widget';
|
||||
import { TimeoutTimer } from '../../common/primitives/Async';
|
||||
import { Emitter, IEvent } from '../../common/primitives/Event';
|
||||
import { IDisposable, dispose } from '../../common/primitives/Lifecycle';
|
||||
import * as platform from '../../common/primitives/Platform';
|
||||
import { TimeoutTimer } from '../../common/Async';
|
||||
import { Emitter, IEvent } from '../../common/Event';
|
||||
import { IDisposable, dispose } from '../../common/Lifecycle';
|
||||
import * as platform from '../../common/Platform';
|
||||
import { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, IScrollEvent, Scrollable, ScrollbarVisibility } from './scrollable';
|
||||
// import 'vs/css!./media/scrollbars';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { GlobalPointerMoveMonitor } from './globalPointerMoveMonitor';
|
||||
import { Widget } from './widget';
|
||||
import { TimeoutTimer } from '../../common/primitives/Async';
|
||||
import { TimeoutTimer } from '../../common/Async';
|
||||
import * as dom from '../Dom';
|
||||
|
||||
export interface IScrollbarArrowOptions {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { FastDomNode } from './fastDomNode';
|
||||
import { TimeoutTimer } from '../../common/primitives/Async';
|
||||
import { Disposable } from '../../common/primitives/Lifecycle';
|
||||
import { TimeoutTimer } from '../../common/Async';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
import { ScrollbarVisibility } from './scrollable';
|
||||
|
||||
export class ScrollbarVisibilityController extends Disposable {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as DomUtils from '../Dom';
|
||||
import { Disposable, IDisposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { Disposable, IDisposable, toDisposable } from '../../common/Lifecycle';
|
||||
|
||||
const mainWindow = (typeof window === 'object' ? window : globalThis) as Window & typeof globalThis;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as dom from '../Dom';
|
||||
import { IMouseEvent, StandardMouseEvent } from './mouseEvent';
|
||||
import { Disposable } from '../../common/primitives/Lifecycle';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
|
||||
export abstract class Widget extends Disposable {
|
||||
|
||||
|
||||
@@ -64,13 +64,6 @@ describe('SelectionModel', () => {
|
||||
assert.deepEqual(model.finalSelectionStart, undefined);
|
||||
assert.deepEqual(model.finalSelectionEnd, undefined);
|
||||
});
|
||||
it('should reset selection start to origin when start row is trimmed', () => {
|
||||
model.selectionStart = [50, 0];
|
||||
model.selectionEnd = [10, 2];
|
||||
assert.equal(model.handleTrim(1), true);
|
||||
assert.deepEqual(model.finalSelectionStart, [0, 0]);
|
||||
assert.deepEqual(model.finalSelectionEnd, [10, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('finalSelectionStart', () => {
|
||||
|
||||
@@ -88,7 +88,7 @@ export class SelectionModel {
|
||||
return [startPlusLength, this.selectionStart[1]];
|
||||
}
|
||||
|
||||
// Ensure the the word/line is selected after a double/triple click
|
||||
// Ensure the word/line is selected after a double/triple click
|
||||
if (this.selectionStartLength) {
|
||||
// Select the larger of the two when start and end are on the same line
|
||||
if (this.selectionEnd[1] === this.selectionStart[1]) {
|
||||
@@ -135,10 +135,9 @@ export class SelectionModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the selection start row is trimmed away, reset to the buffer origin.
|
||||
// If the selection start is trimmed, ensure the start column is 0.
|
||||
if (this.selectionStart && this.selectionStart[1] < 0) {
|
||||
this.selectionStart = [0, 0];
|
||||
return true;
|
||||
this.selectionStart[1] = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { IOptionsService } from '../../common/services/Services';
|
||||
import { ICharSizeService } from './Services';
|
||||
import { Disposable } from '../../common/primitives/Lifecycle';
|
||||
import { Emitter } from '../../common/primitives/Event';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
import { Emitter } from '../../common/Event';
|
||||
|
||||
export class CharSizeService extends Disposable implements ICharSizeService {
|
||||
public serviceBrand: undefined;
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
import { assert } from 'chai';
|
||||
import { ICharacterJoinerService } from './Services';
|
||||
import { CharacterJoinerService } from './CharacterJoinerService';
|
||||
import { BufferLine } from '../../common/primitives/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from '../../common/primitives/buffer/BufferLineStringCache';
|
||||
import { IBufferLine } from '../../common/primitives/buffer/Types';
|
||||
import { CellData } from '../../common/primitives/buffer/CellData';
|
||||
import { BufferLine } from '../../common/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from '../../common/buffer/BufferLineStringCache';
|
||||
import { IBufferLine } from '../../common/buffer/Types';
|
||||
import { CellData } from '../../common/buffer/CellData';
|
||||
import { MockBufferService, createCellData } from '../../common/TestUtils.test';
|
||||
|
||||
const TEST_STRING_CACHE = new BufferLineStringCache();
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { CharData, IBufferLine, ICellData } from '../../common/primitives/buffer/Types';
|
||||
import { CharData, IBufferLine, ICellData } from '../../common/buffer/Types';
|
||||
import { ICharacterJoiner } from '../Types';
|
||||
import { AttributeData } from '../../common/primitives/buffer/AttributeData';
|
||||
import { WHITESPACE_CELL_CHAR, Content } from '../../common/primitives/buffer/Constants';
|
||||
import { CellData } from '../../common/primitives/buffer/CellData';
|
||||
import { AttributeData } from '../../common/buffer/AttributeData';
|
||||
import { WHITESPACE_CELL_CHAR, Content } from '../../common/buffer/Constants';
|
||||
import { CellData } from '../../common/buffer/CellData';
|
||||
import { IBufferService } from '../../common/services/Services';
|
||||
import { ICharacterJoinerService } from './Services';
|
||||
|
||||
@@ -100,7 +100,6 @@ export class CharacterJoinerService implements ICharacterJoinerService {
|
||||
|
||||
const ranges: [number, number][] = [];
|
||||
const lineStr = line.translateToString(true);
|
||||
const trimmedLength = line.getTrimmedLength();
|
||||
|
||||
// Because some cells can be represented by multiple javascript characters,
|
||||
// we track the cell and the string indexes separately. This allows us to
|
||||
@@ -112,7 +111,7 @@ export class CharacterJoinerService implements ICharacterJoinerService {
|
||||
let rangeAttrFG = line.getFg(0);
|
||||
let rangeAttrBG = line.getBg(0);
|
||||
|
||||
for (let x = 0; x < trimmedLength; x++) {
|
||||
for (let x = 0; x < line.getTrimmedLength(); x++) {
|
||||
line.loadCell(x, this._workCell);
|
||||
|
||||
if (this._workCell.getWidth() === 0) {
|
||||
@@ -148,7 +147,7 @@ export class CharacterJoinerService implements ICharacterJoinerService {
|
||||
}
|
||||
|
||||
// Process any trailing ranges.
|
||||
if (trimmedLength - rangeStartColumn > 1) {
|
||||
if (this._bufferService.cols - rangeStartColumn > 1) {
|
||||
const joinedRanges = this._getJoinedRanges(
|
||||
lineStr,
|
||||
rangeStartStringIndex,
|
||||
@@ -217,8 +216,7 @@ export class CharacterJoinerService implements ICharacterJoinerService {
|
||||
return;
|
||||
}
|
||||
|
||||
const trimmedLength = line.getTrimmedLength();
|
||||
for (let x = startCol; x < trimmedLength; x++) {
|
||||
for (let x = startCol; x < this._bufferService.cols; x++) {
|
||||
const width = line.getWidth(x);
|
||||
const length = line.getString(x).length || WHITESPACE_CELL_CHAR.length;
|
||||
|
||||
@@ -266,7 +264,7 @@ export class CharacterJoinerService implements ICharacterJoinerService {
|
||||
// If there is still a range left at the end, it must extend all the way to
|
||||
// the end of the line.
|
||||
if (currentRange) {
|
||||
currentRange[1] = trimmedLength;
|
||||
currentRange[1] = this._bufferService.cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
*/
|
||||
|
||||
import { ICoreBrowserService } from './Services';
|
||||
import { Emitter, EventUtils } from '../../common/primitives/Event';
|
||||
import { Emitter, EventUtils } from '../../common/Event';
|
||||
import { addDisposableListener } from '../Dom';
|
||||
import { Disposable, MutableDisposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { Disposable, MutableDisposable, toDisposable } from '../../common/Lifecycle';
|
||||
|
||||
export class CoreBrowserService extends Disposable implements ICoreBrowserService {
|
||||
public serviceBrand: undefined;
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
*/
|
||||
|
||||
import { IKeyboardService } from './Services';
|
||||
import { evaluateKeyboardEvent } from '../../common/primitives/input/Keyboard';
|
||||
import { KittyKeyboard, KittyKeyboardEventType, KittyKeyboardFlags } from '../../common/primitives/input/KittyKeyboard';
|
||||
import { Win32InputMode } from '../../common/primitives/input/Win32InputMode';
|
||||
import { isMac } from '../../common/primitives/Platform';
|
||||
import { evaluateKeyboardEvent } from '../../common/input/Keyboard';
|
||||
import { KittyKeyboard, KittyKeyboardEventType, KittyKeyboardFlags } from '../../common/input/KittyKeyboard';
|
||||
import { Win32InputMode } from '../../common/input/Win32InputMode';
|
||||
import { isMac } from '../../common/Platform';
|
||||
import { ICoreService, IOptionsService } from '../../common/services/Services';
|
||||
import { IKeyboardResult } from '../../common/primitives/Types';
|
||||
import { IKeyboardResult } from '../../common/Types';
|
||||
|
||||
export class KeyboardService implements IKeyboardService {
|
||||
public serviceBrand: undefined;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ILinkProvider, ILinkProviderService } from './Services';
|
||||
import { Disposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { IDisposable } from '../../common/primitives/Types';
|
||||
import { Disposable, toDisposable } from '../../common/Lifecycle';
|
||||
import { IDisposable } from '../../common/Types';
|
||||
|
||||
export class LinkProviderService extends Disposable implements ILinkProviderService {
|
||||
declare public serviceBrand: undefined;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { assert } from 'chai';
|
||||
import { AltMouseCursorController, MouseEventCssClasses, MouseService } from './MouseService';
|
||||
import { MouseStateService } from '../../common/services/MouseStateService';
|
||||
import { CoreMouseAction, CoreMouseButton } from '../../common/primitives/Types';
|
||||
import { CoreMouseAction, CoreMouseButton } from '../../common/Types';
|
||||
import { IBufferService, ICoreService, ILogService, IOptionsService } from '../../common/services/Services';
|
||||
import { OptionsService } from '../../common/services/OptionsService';
|
||||
import { MockCoreBrowserService, MockRenderService, MockSelectionService } from '../TestUtils.test';
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import { addDisposableListener } from '../Dom';
|
||||
import { IBufferService, IMouseStateService, ICoreService, ILogService, IOptionsService } from '../../common/services/Services';
|
||||
import { CoreMouseAction, CoreMouseButton, CoreMouseEventType, ICoreMouseEvent, IDisposable } from '../../common/primitives/Types';
|
||||
import { C0 } from '../../common/primitives/data/EscapeSequences';
|
||||
import { DisposableStore, MutableDisposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { CoreMouseAction, CoreMouseButton, CoreMouseEventType, ICoreMouseEvent, IDisposable } from '../../common/Types';
|
||||
import { C0 } from '../../common/data/EscapeSequences';
|
||||
import { DisposableStore, MutableDisposable, toDisposable } from '../../common/Lifecycle';
|
||||
import { ICoreBrowserService, IMouseCoordsService, IMouseService, IMouseServiceTarget, IRenderService, ISelectionService } from './Services';
|
||||
import { Gesture, EventType as GestureEventType, IGestureEvent } from '../scrollable/touch';
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import { RenderDebouncer } from '../RenderDebouncer';
|
||||
import { IRenderDebouncerWithCallback } from '../Types';
|
||||
import { IRenderDimensions, IRenderer } from '../renderer/shared/Types';
|
||||
import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from './Services';
|
||||
import { Disposable, MutableDisposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import { DebouncedIdleTask } from '../../common/primitives/TaskQueue';
|
||||
import { Disposable, MutableDisposable, toDisposable } from '../../common/Lifecycle';
|
||||
import { DebouncedIdleTask } from '../../common/TaskQueue';
|
||||
import { IBufferService, ICoreService, IDecorationService, ILogService, IOptionsService } from '../../common/services/Services';
|
||||
import { Emitter } from '../../common/primitives/Event';
|
||||
import { Emitter } from '../../common/Event';
|
||||
|
||||
interface ISelectionState {
|
||||
start: [number, number] | undefined;
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
import { assert } from 'chai';
|
||||
import { SelectionService, SelectionMode } from './SelectionService';
|
||||
import { SelectionModel } from '../selection/SelectionModel';
|
||||
import { IBuffer, IBufferLine } from '../../common/primitives/buffer/Types';
|
||||
import { IBuffer, IBufferLine } from '../../common/buffer/Types';
|
||||
import { MockBufferService, MockOptionsService, MockCoreService, MockMouseStateService, createCellData } from '../../common/TestUtils.test';
|
||||
import { BufferLine } from '../../common/primitives/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from '../../common/primitives/buffer/BufferLineStringCache';
|
||||
import { BufferLine } from '../../common/buffer/BufferLine';
|
||||
import { BufferLineStringCache } from '../../common/buffer/BufferLineStringCache';
|
||||
import { IBufferService, IOptionsService } from '../../common/services/Services';
|
||||
import { MockCoreBrowserService, MockMouseService, MockRenderService } from '../TestUtils.test';
|
||||
import { CellData } from '../../common/primitives/buffer/CellData';
|
||||
import { CellData } from '../../common/buffer/CellData';
|
||||
import { IRenderService } from './Services';
|
||||
|
||||
const TEST_STRING_CACHE = new BufferLineStringCache();
|
||||
|
||||
@@ -9,14 +9,14 @@ import { moveToCellSequence } from '../input/MoveToCell';
|
||||
import { SelectionModel } from '../selection/SelectionModel';
|
||||
import { ISelectionRedrawRequestEvent, ISelectionRequestScrollLinesEvent } from '../selection/Types';
|
||||
import { ICoreBrowserService, IMouseCoordsService, IRenderService, ISelectionService } from './Services';
|
||||
import { Disposable, MutableDisposable, toDisposable } from '../../common/primitives/Lifecycle';
|
||||
import * as Browser from '../../common/primitives/Platform';
|
||||
import { IDisposable } from '../../common/primitives/Types';
|
||||
import { IBuffer, IBufferLine, ICellData } from '../../common/primitives/buffer/Types';
|
||||
import { getRangeLength } from '../../common/primitives/buffer/BufferRange';
|
||||
import { CellData } from '../../common/primitives/buffer/CellData';
|
||||
import { Disposable, MutableDisposable, toDisposable } from '../../common/Lifecycle';
|
||||
import * as Browser from '../../common/Platform';
|
||||
import { IDisposable } from '../../common/Types';
|
||||
import { IBuffer, IBufferLine, ICellData } from '../../common/buffer/Types';
|
||||
import { getRangeLength } from '../../common/buffer/BufferRange';
|
||||
import { CellData } from '../../common/buffer/CellData';
|
||||
import { IBufferService, ICoreService, IMouseStateService, IOptionsService } from '../../common/services/Services';
|
||||
import { Emitter } from '../../common/primitives/Event';
|
||||
import { Emitter } from '../../common/Event';
|
||||
|
||||
const enum Constants {
|
||||
/**
|
||||
@@ -704,7 +704,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
if (this._activeSelectionMode !== SelectionMode.COLUMN) {
|
||||
this._model.selectionEnd[0] = this._bufferService.cols;
|
||||
}
|
||||
this._model.selectionEnd[1] = Math.min(buffer.ydisp + this._bufferService.rows - 1, buffer.lines.length - 1);
|
||||
this._model.selectionEnd[1] = Math.min(buffer.ydisp + this._bufferService.rows, buffer.lines.length - 1);
|
||||
} else {
|
||||
if (this._activeSelectionMode !== SelectionMode.COLUMN) {
|
||||
this._model.selectionEnd[0] = 0;
|
||||
@@ -927,7 +927,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
// Incremenet the end index so it is at the start of the next character
|
||||
endIndex++;
|
||||
|
||||
// Calculate the start _column_, converting the the string indexes back to
|
||||
// Calculate the start _column_, converting the string indexes back to
|
||||
// column coordinates.
|
||||
let start =
|
||||
startIndex // The index of the selection's start char in the line string
|
||||
@@ -935,7 +935,7 @@ export class SelectionService extends Disposable implements ISelectionService {
|
||||
- leftWideCharCount // The number of wide chars left of the initial char
|
||||
+ leftLongCharOffset; // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis)
|
||||
|
||||
// Calculate the length in _columns_, converting the the string indexes back
|
||||
// Calculate the length in _columns_, converting the string indexes back
|
||||
// to column coordinates.
|
||||
let length = Math.min(this._bufferService.cols, // Disallow lengths larger than the terminal cols
|
||||
endIndex // The index of the selection's end char in the line string
|
||||
|
||||
@@ -7,8 +7,8 @@ import { IRenderDimensions, IRenderer } from '../renderer/shared/Types';
|
||||
import { IColorSet, ILink, ReadonlyColorSet } from '../Types';
|
||||
import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from '../selection/Types';
|
||||
import { createDecorator } from '../../common/services/ServiceRegistry';
|
||||
import { AllColorIndex, IDisposable, IKeyboardResult } from '../../common/primitives/Types';
|
||||
import type { IEvent } from '../../common/primitives/Event';
|
||||
import { AllColorIndex, IDisposable, IKeyboardResult } from '../../common/Types';
|
||||
import type { IEvent } from '../../common/Event';
|
||||
|
||||
export const ICharSizeService = createDecorator<ICharSizeService>('CharSizeService');
|
||||
export interface ICharSizeService {
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
import { ColorContrastCache } from '../ColorContrastCache';
|
||||
import { IThemeService } from './Services';
|
||||
import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from '../Types';
|
||||
import { color, css, NULL_COLOR } from '../../common/primitives/Color';
|
||||
import { Disposable } from '../../common/primitives/Lifecycle';
|
||||
import { color, css, NULL_COLOR } from '../../common/Color';
|
||||
import { Disposable } from '../../common/Lifecycle';
|
||||
import { IOptionsService, ITheme } from '../../common/services/Services';
|
||||
import { AllColorIndex, IColor, SpecialColorIndex } from '../../common/primitives/Types';
|
||||
import { Emitter } from '../../common/primitives/Event';
|
||||
import { AllColorIndex, IColor, SpecialColorIndex } from '../../common/Types';
|
||||
import { Emitter } from '../../common/Event';
|
||||
|
||||
interface IRestoreColorSet {
|
||||
foreground: IColor;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user