@xterm/xterm 5.6.0-beta.8 → 5.6.0-beta.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/css/xterm.css +71 -4
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +53 -0
- package/lib/xterm.mjs.map +7 -0
- package/package.json +43 -33
- package/src/browser/AccessibilityManager.ts +53 -25
- package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +139 -148
- package/src/browser/Linkifier.ts +26 -14
- package/src/browser/LocalizableStrings.ts +15 -4
- package/src/browser/{Types.d.ts → Types.ts} +67 -15
- package/src/browser/Viewport.ts +143 -370
- package/src/browser/decorations/BufferDecorationRenderer.ts +14 -9
- package/src/browser/decorations/OverviewRulerRenderer.ts +40 -44
- package/src/browser/public/Terminal.ts +25 -19
- package/src/browser/renderer/dom/DomRenderer.ts +22 -19
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +35 -15
- package/src/browser/renderer/shared/CharAtlasUtils.ts +4 -0
- package/src/browser/renderer/shared/CustomGlyphs.ts +6 -0
- package/src/browser/renderer/shared/DevicePixelObserver.ts +1 -2
- package/src/browser/renderer/shared/TextureAtlas.ts +3 -3
- package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +4 -4
- package/src/browser/services/CharSizeService.ts +6 -6
- package/src/browser/services/CoreBrowserService.ts +15 -15
- package/src/browser/services/LinkProviderService.ts +2 -2
- package/src/browser/services/RenderService.ts +20 -20
- package/src/browser/services/SelectionService.ts +8 -8
- package/src/browser/services/Services.ts +13 -13
- package/src/browser/services/ThemeService.ts +19 -58
- package/src/browser/shared/Constants.ts +8 -0
- package/src/common/CircularList.ts +5 -5
- package/src/common/CoreTerminal.ts +35 -41
- package/src/common/InputHandler.ts +63 -51
- package/src/common/{Types.d.ts → Types.ts} +13 -17
- package/src/common/buffer/Buffer.ts +15 -7
- package/src/common/buffer/BufferReflow.ts +9 -6
- package/src/common/buffer/BufferSet.ts +5 -5
- package/src/common/buffer/Marker.ts +4 -4
- package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
- package/src/common/input/WriteBuffer.ts +3 -3
- package/src/common/parser/EscapeSequenceParser.ts +4 -4
- package/src/common/public/BufferNamespaceApi.ts +3 -3
- package/src/common/services/BufferService.ts +7 -7
- package/src/common/services/CoreMouseService.ts +5 -3
- package/src/common/services/CoreService.ts +8 -6
- package/src/common/services/DecorationService.ts +8 -9
- package/src/common/services/InstantiationService.ts +1 -1
- package/src/common/services/LogService.ts +2 -2
- package/src/common/services/OptionsService.ts +6 -5
- package/src/common/services/ServiceRegistry.ts +1 -1
- package/src/common/services/Services.ts +26 -17
- package/src/common/services/UnicodeService.ts +2 -2
- package/src/vs/base/browser/browser.ts +141 -0
- package/src/vs/base/browser/canIUse.ts +49 -0
- package/src/vs/base/browser/dom.ts +2369 -0
- package/src/vs/base/browser/fastDomNode.ts +316 -0
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
- package/src/vs/base/browser/iframe.ts +135 -0
- package/src/vs/base/browser/keyboardEvent.ts +213 -0
- package/src/vs/base/browser/mouseEvent.ts +229 -0
- package/src/vs/base/browser/touch.ts +372 -0
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
- package/src/vs/base/browser/ui/widget.ts +57 -0
- package/src/vs/base/browser/window.ts +14 -0
- package/src/vs/base/common/arrays.ts +887 -0
- package/src/vs/base/common/arraysFind.ts +202 -0
- package/src/vs/base/common/assert.ts +71 -0
- package/src/vs/base/common/async.ts +1992 -0
- package/src/vs/base/common/cancellation.ts +148 -0
- package/src/vs/base/common/charCode.ts +450 -0
- package/src/vs/base/common/collections.ts +140 -0
- package/src/vs/base/common/decorators.ts +130 -0
- package/src/vs/base/common/equals.ts +146 -0
- package/src/vs/base/common/errors.ts +303 -0
- package/src/vs/base/common/event.ts +1778 -0
- package/src/vs/base/common/functional.ts +32 -0
- package/src/vs/base/common/hash.ts +316 -0
- package/src/vs/base/common/iterator.ts +159 -0
- package/src/vs/base/common/keyCodes.ts +526 -0
- package/src/vs/base/common/keybindings.ts +284 -0
- package/src/vs/base/common/lazy.ts +47 -0
- package/src/vs/base/common/lifecycle.ts +801 -0
- package/src/vs/base/common/linkedList.ts +142 -0
- package/src/vs/base/common/map.ts +202 -0
- package/src/vs/base/common/numbers.ts +98 -0
- package/src/vs/base/common/observable.ts +76 -0
- package/src/vs/base/common/observableInternal/api.ts +31 -0
- package/src/vs/base/common/observableInternal/autorun.ts +281 -0
- package/src/vs/base/common/observableInternal/base.ts +489 -0
- package/src/vs/base/common/observableInternal/debugName.ts +145 -0
- package/src/vs/base/common/observableInternal/derived.ts +428 -0
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
- package/src/vs/base/common/observableInternal/logging.ts +328 -0
- package/src/vs/base/common/observableInternal/promise.ts +209 -0
- package/src/vs/base/common/observableInternal/utils.ts +610 -0
- package/src/vs/base/common/platform.ts +281 -0
- package/src/vs/base/common/scrollable.ts +522 -0
- package/src/vs/base/common/sequence.ts +34 -0
- package/src/vs/base/common/stopwatch.ts +43 -0
- package/src/vs/base/common/strings.ts +557 -0
- package/src/vs/base/common/symbols.ts +9 -0
- package/src/vs/base/common/uint.ts +59 -0
- package/src/vs/patches/nls.ts +90 -0
- package/src/vs/typings/base-common.d.ts +20 -0
- package/src/vs/typings/require.d.ts +42 -0
- package/src/vs/typings/thenable.d.ts +12 -0
- package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
- package/src/vs/typings/vscode-globals-product.d.ts +33 -0
- package/typings/xterm.d.ts +66 -15
- package/src/browser/Lifecycle.ts +0 -33
- package/src/common/EventEmitter.ts +0 -78
- package/src/common/Lifecycle.ts +0 -108
- /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
- /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
|
|
6
|
+
import { CharCode } from 'vs/base/common/charCode';
|
|
7
|
+
import { Constants } from 'vs/base/common/uint';
|
|
8
|
+
|
|
9
|
+
export function isFalsyOrWhitespace(str: string | undefined): boolean {
|
|
10
|
+
if (!str || typeof str !== 'string') {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return str.trim().length === 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const _formatRegexp = /{(\d+)}/g;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Helper to produce a string with a variable number of arguments. Insert variable segments
|
|
20
|
+
* into the string using the {n} notation where N is the index of the argument following the string.
|
|
21
|
+
* @param value string to which formatting is applied
|
|
22
|
+
* @param args replacements for {n}-entries
|
|
23
|
+
*/
|
|
24
|
+
export function format(value: string, ...args: any[]): string {
|
|
25
|
+
if (args.length === 0) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
return value.replace(_formatRegexp, function (match, group) {
|
|
29
|
+
const idx = parseInt(group, 10);
|
|
30
|
+
return isNaN(idx) || idx < 0 || idx >= args.length ?
|
|
31
|
+
match :
|
|
32
|
+
args[idx];
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const _format2Regexp = /{([^}]+)}/g;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Helper to create a string from a template and a string record.
|
|
40
|
+
* Similar to `format` but with objects instead of positional arguments.
|
|
41
|
+
*/
|
|
42
|
+
export function format2(template: string, values: Record<string, unknown>): string {
|
|
43
|
+
if (Object.keys(values).length === 0) {
|
|
44
|
+
return template;
|
|
45
|
+
}
|
|
46
|
+
return template.replace(_format2Regexp, (match, group) => (values[group] ?? match) as string);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Encodes the given value so that it can be used as literal value in html attributes.
|
|
51
|
+
*
|
|
52
|
+
* In other words, computes `$val`, such that `attr` in `<div attr="$val" />` has the runtime value `value`.
|
|
53
|
+
* This prevents XSS injection.
|
|
54
|
+
*/
|
|
55
|
+
export function htmlAttributeEncodeValue(value: string): string {
|
|
56
|
+
return value.replace(/[<>"'&]/g, ch => {
|
|
57
|
+
switch (ch) {
|
|
58
|
+
case '<': return '<';
|
|
59
|
+
case '>': return '>';
|
|
60
|
+
case '"': return '"';
|
|
61
|
+
case '\'': return ''';
|
|
62
|
+
case '&': return '&';
|
|
63
|
+
}
|
|
64
|
+
return ch;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Converts HTML characters inside the string to use entities instead. Makes the string safe from
|
|
70
|
+
* being used e.g. in HTMLElement.innerHTML.
|
|
71
|
+
*/
|
|
72
|
+
export function escape(html: string): string {
|
|
73
|
+
return html.replace(/[<>&]/g, function (match) {
|
|
74
|
+
switch (match) {
|
|
75
|
+
case '<': return '<';
|
|
76
|
+
case '>': return '>';
|
|
77
|
+
case '&': return '&';
|
|
78
|
+
default: return match;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Escapes regular expression characters in a given string
|
|
85
|
+
*/
|
|
86
|
+
export function escapeRegExpCharacters(value: string): string {
|
|
87
|
+
return value.replace(/[\\\{\}\*\+\?\|\^\$\.\[\]\(\)]/g, '\\$&');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Counts how often `substr` occurs inside `value`.
|
|
92
|
+
*/
|
|
93
|
+
export function count(value: string, substr: string): number {
|
|
94
|
+
let result = 0;
|
|
95
|
+
let index = value.indexOf(substr);
|
|
96
|
+
while (index !== -1) {
|
|
97
|
+
result++;
|
|
98
|
+
index = value.indexOf(substr, index + substr.length);
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function truncate(value: string, maxLength: number, suffix = '…'): string {
|
|
104
|
+
if (value.length <= maxLength) {
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return `${value.substr(0, maxLength)}${suffix}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function truncateMiddle(value: string, maxLength: number, suffix = '…'): string {
|
|
112
|
+
if (value.length <= maxLength) {
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const prefixLength = Math.ceil(maxLength / 2) - suffix.length / 2;
|
|
117
|
+
const suffixLength = Math.floor(maxLength / 2) - suffix.length / 2;
|
|
118
|
+
|
|
119
|
+
return `${value.substr(0, prefixLength)}${suffix}${value.substr(value.length - suffixLength)}`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Removes all occurrences of needle from the beginning and end of haystack.
|
|
124
|
+
* @param haystack string to trim
|
|
125
|
+
* @param needle the thing to trim (default is a blank)
|
|
126
|
+
*/
|
|
127
|
+
export function trim(haystack: string, needle: string = ' '): string {
|
|
128
|
+
const trimmed = ltrim(haystack, needle);
|
|
129
|
+
return rtrim(trimmed, needle);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Removes all occurrences of needle from the beginning of haystack.
|
|
134
|
+
* @param haystack string to trim
|
|
135
|
+
* @param needle the thing to trim
|
|
136
|
+
*/
|
|
137
|
+
export function ltrim(haystack: string, needle: string): string {
|
|
138
|
+
if (!haystack || !needle) {
|
|
139
|
+
return haystack;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const needleLen = needle.length;
|
|
143
|
+
if (needleLen === 0 || haystack.length === 0) {
|
|
144
|
+
return haystack;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let offset = 0;
|
|
148
|
+
|
|
149
|
+
while (haystack.indexOf(needle, offset) === offset) {
|
|
150
|
+
offset = offset + needleLen;
|
|
151
|
+
}
|
|
152
|
+
return haystack.substring(offset);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Removes all occurrences of needle from the end of haystack.
|
|
157
|
+
* @param haystack string to trim
|
|
158
|
+
* @param needle the thing to trim
|
|
159
|
+
*/
|
|
160
|
+
export function rtrim(haystack: string, needle: string): string {
|
|
161
|
+
if (!haystack || !needle) {
|
|
162
|
+
return haystack;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const needleLen = needle.length,
|
|
166
|
+
haystackLen = haystack.length;
|
|
167
|
+
|
|
168
|
+
if (needleLen === 0 || haystackLen === 0) {
|
|
169
|
+
return haystack;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let offset = haystackLen,
|
|
173
|
+
idx = -1;
|
|
174
|
+
|
|
175
|
+
while (true) {
|
|
176
|
+
idx = haystack.lastIndexOf(needle, offset - 1);
|
|
177
|
+
if (idx === -1 || idx + needleLen !== offset) {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
if (idx === 0) {
|
|
181
|
+
return '';
|
|
182
|
+
}
|
|
183
|
+
offset = idx;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return haystack.substring(0, offset);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function convertSimple2RegExpPattern(pattern: string): string {
|
|
190
|
+
return pattern.replace(/[\-\\\{\}\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&').replace(/[\*]/g, '.*');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function stripWildcards(pattern: string): string {
|
|
194
|
+
return pattern.replace(/\*/g, '');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface RegExpOptions {
|
|
198
|
+
matchCase?: boolean;
|
|
199
|
+
wholeWord?: boolean;
|
|
200
|
+
multiline?: boolean;
|
|
201
|
+
global?: boolean;
|
|
202
|
+
unicode?: boolean;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function createRegExp(searchString: string, isRegex: boolean, options: RegExpOptions = {}): RegExp {
|
|
206
|
+
if (!searchString) {
|
|
207
|
+
throw new Error('Cannot create regex from empty string');
|
|
208
|
+
}
|
|
209
|
+
if (!isRegex) {
|
|
210
|
+
searchString = escapeRegExpCharacters(searchString);
|
|
211
|
+
}
|
|
212
|
+
if (options.wholeWord) {
|
|
213
|
+
if (!/\B/.test(searchString.charAt(0))) {
|
|
214
|
+
searchString = '\\b' + searchString;
|
|
215
|
+
}
|
|
216
|
+
if (!/\B/.test(searchString.charAt(searchString.length - 1))) {
|
|
217
|
+
searchString = searchString + '\\b';
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
let modifiers = '';
|
|
221
|
+
if (options.global) {
|
|
222
|
+
modifiers += 'g';
|
|
223
|
+
}
|
|
224
|
+
if (!options.matchCase) {
|
|
225
|
+
modifiers += 'i';
|
|
226
|
+
}
|
|
227
|
+
if (options.multiline) {
|
|
228
|
+
modifiers += 'm';
|
|
229
|
+
}
|
|
230
|
+
if (options.unicode) {
|
|
231
|
+
modifiers += 'u';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return new RegExp(searchString, modifiers);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean {
|
|
238
|
+
// Exit early if it's one of these special cases which are meant to match
|
|
239
|
+
// against an empty string
|
|
240
|
+
if (regexp.source === '^' || regexp.source === '^$' || regexp.source === '$' || regexp.source === '^\\s*$') {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// We check against an empty string. If the regular expression doesn't advance
|
|
245
|
+
// (e.g. ends in an endless loop) it will match an empty string.
|
|
246
|
+
const match = regexp.exec('');
|
|
247
|
+
return !!(match && regexp.lastIndex === 0);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function splitLines(str: string): string[] {
|
|
251
|
+
return str.split(/\r\n|\r|\n/);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function splitLinesIncludeSeparators(str: string): string[] {
|
|
255
|
+
const linesWithSeparators: string[] = [];
|
|
256
|
+
const splitLinesAndSeparators = str.split(/(\r\n|\r|\n)/);
|
|
257
|
+
for (let i = 0; i < Math.ceil(splitLinesAndSeparators.length / 2); i++) {
|
|
258
|
+
linesWithSeparators.push(splitLinesAndSeparators[2 * i] + (splitLinesAndSeparators[2 * i + 1] ?? ''));
|
|
259
|
+
}
|
|
260
|
+
return linesWithSeparators;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Returns first index of the string that is not whitespace.
|
|
265
|
+
* If string is empty or contains only whitespaces, returns -1
|
|
266
|
+
*/
|
|
267
|
+
export function firstNonWhitespaceIndex(str: string): number {
|
|
268
|
+
for (let i = 0, len = str.length; i < len; i++) {
|
|
269
|
+
const chCode = str.charCodeAt(i);
|
|
270
|
+
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
|
|
271
|
+
return i;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return -1;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Returns the leading whitespace of the string.
|
|
279
|
+
* If the string contains only whitespaces, returns entire string
|
|
280
|
+
*/
|
|
281
|
+
export function getLeadingWhitespace(str: string, start: number = 0, end: number = str.length): string {
|
|
282
|
+
for (let i = start; i < end; i++) {
|
|
283
|
+
const chCode = str.charCodeAt(i);
|
|
284
|
+
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
|
|
285
|
+
return str.substring(start, i);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return str.substring(start, end);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Returns last index of the string that is not whitespace.
|
|
293
|
+
* If string is empty or contains only whitespaces, returns -1
|
|
294
|
+
*/
|
|
295
|
+
export function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number {
|
|
296
|
+
for (let i = startIndex; i >= 0; i--) {
|
|
297
|
+
const chCode = str.charCodeAt(i);
|
|
298
|
+
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
|
|
299
|
+
return i;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return -1;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Function that works identically to String.prototype.replace, except, the
|
|
307
|
+
* replace function is allowed to be async and return a Promise.
|
|
308
|
+
*/
|
|
309
|
+
export function replaceAsync(str: string, search: RegExp, replacer: (match: string, ...args: any[]) => Promise<string>): Promise<string> {
|
|
310
|
+
const parts: (string | Promise<string>)[] = [];
|
|
311
|
+
|
|
312
|
+
let last = 0;
|
|
313
|
+
for (const match of str.matchAll(search)) {
|
|
314
|
+
parts.push(str.slice(last, match.index));
|
|
315
|
+
if (match.index === undefined) {
|
|
316
|
+
throw new Error('match.index should be defined');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
last = match.index + match[0].length;
|
|
320
|
+
parts.push(replacer(match[0], ...match.slice(1), match.index, str, match.groups));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
parts.push(str.slice(last));
|
|
324
|
+
|
|
325
|
+
return Promise.all(parts).then(p => p.join(''));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function compare(a: string, b: string): number {
|
|
329
|
+
if (a < b) {
|
|
330
|
+
return -1;
|
|
331
|
+
} else if (a > b) {
|
|
332
|
+
return 1;
|
|
333
|
+
} else {
|
|
334
|
+
return 0;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function compareSubstring(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
|
|
339
|
+
for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
|
|
340
|
+
const codeA = a.charCodeAt(aStart);
|
|
341
|
+
const codeB = b.charCodeAt(bStart);
|
|
342
|
+
if (codeA < codeB) {
|
|
343
|
+
return -1;
|
|
344
|
+
} else if (codeA > codeB) {
|
|
345
|
+
return 1;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const aLen = aEnd - aStart;
|
|
349
|
+
const bLen = bEnd - bStart;
|
|
350
|
+
if (aLen < bLen) {
|
|
351
|
+
return -1;
|
|
352
|
+
} else if (aLen > bLen) {
|
|
353
|
+
return 1;
|
|
354
|
+
}
|
|
355
|
+
return 0;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function compareIgnoreCase(a: string, b: string): number {
|
|
359
|
+
return compareSubstringIgnoreCase(a, b, 0, a.length, 0, b.length);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function compareSubstringIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
|
|
363
|
+
|
|
364
|
+
for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
|
|
365
|
+
|
|
366
|
+
let codeA = a.charCodeAt(aStart);
|
|
367
|
+
let codeB = b.charCodeAt(bStart);
|
|
368
|
+
|
|
369
|
+
if (codeA === codeB) {
|
|
370
|
+
// equal
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (codeA >= 128 || codeB >= 128) {
|
|
375
|
+
// not ASCII letters -> fallback to lower-casing strings
|
|
376
|
+
return compareSubstring(a.toLowerCase(), b.toLowerCase(), aStart, aEnd, bStart, bEnd);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// mapper lower-case ascii letter onto upper-case varinats
|
|
380
|
+
// [97-122] (lower ascii) --> [65-90] (upper ascii)
|
|
381
|
+
if (isLowerAsciiLetter(codeA)) {
|
|
382
|
+
codeA -= 32;
|
|
383
|
+
}
|
|
384
|
+
if (isLowerAsciiLetter(codeB)) {
|
|
385
|
+
codeB -= 32;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// compare both code points
|
|
389
|
+
const diff = codeA - codeB;
|
|
390
|
+
if (diff === 0) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return diff;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const aLen = aEnd - aStart;
|
|
398
|
+
const bLen = bEnd - bStart;
|
|
399
|
+
|
|
400
|
+
if (aLen < bLen) {
|
|
401
|
+
return -1;
|
|
402
|
+
} else if (aLen > bLen) {
|
|
403
|
+
return 1;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return 0;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export function isAsciiDigit(code: number): boolean {
|
|
410
|
+
return code >= CharCode.Digit0 && code <= CharCode.Digit9;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function isLowerAsciiLetter(code: number): boolean {
|
|
414
|
+
return code >= CharCode.a && code <= CharCode.z;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export function isUpperAsciiLetter(code: number): boolean {
|
|
418
|
+
return code >= CharCode.A && code <= CharCode.Z;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export function equalsIgnoreCase(a: string, b: string): boolean {
|
|
422
|
+
return a.length === b.length && compareSubstringIgnoreCase(a, b) === 0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function startsWithIgnoreCase(str: string, candidate: string): boolean {
|
|
426
|
+
const candidateLength = candidate.length;
|
|
427
|
+
if (candidate.length > str.length) {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return compareSubstringIgnoreCase(str, candidate, 0, candidateLength) === 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* @returns the length of the common prefix of the two strings.
|
|
436
|
+
*/
|
|
437
|
+
export function commonPrefixLength(a: string, b: string): number {
|
|
438
|
+
|
|
439
|
+
const len = Math.min(a.length, b.length);
|
|
440
|
+
let i: number;
|
|
441
|
+
|
|
442
|
+
for (i = 0; i < len; i++) {
|
|
443
|
+
if (a.charCodeAt(i) !== b.charCodeAt(i)) {
|
|
444
|
+
return i;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return len;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* @returns the length of the common suffix of the two strings.
|
|
453
|
+
*/
|
|
454
|
+
export function commonSuffixLength(a: string, b: string): number {
|
|
455
|
+
|
|
456
|
+
const len = Math.min(a.length, b.length);
|
|
457
|
+
let i: number;
|
|
458
|
+
|
|
459
|
+
const aLastIndex = a.length - 1;
|
|
460
|
+
const bLastIndex = b.length - 1;
|
|
461
|
+
|
|
462
|
+
for (i = 0; i < len; i++) {
|
|
463
|
+
if (a.charCodeAt(aLastIndex - i) !== b.charCodeAt(bLastIndex - i)) {
|
|
464
|
+
return i;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return len;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* See http://en.wikipedia.org/wiki/Surrogate_pair
|
|
473
|
+
*/
|
|
474
|
+
export function isHighSurrogate(charCode: number): boolean {
|
|
475
|
+
return (0xD800 <= charCode && charCode <= 0xDBFF);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* See http://en.wikipedia.org/wiki/Surrogate_pair
|
|
480
|
+
*/
|
|
481
|
+
export function isLowSurrogate(charCode: number): boolean {
|
|
482
|
+
return (0xDC00 <= charCode && charCode <= 0xDFFF);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* See http://en.wikipedia.org/wiki/Surrogate_pair
|
|
487
|
+
*/
|
|
488
|
+
export function computeCodePoint(highSurrogate: number, lowSurrogate: number): number {
|
|
489
|
+
return ((highSurrogate - 0xD800) << 10) + (lowSurrogate - 0xDC00) + 0x10000;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* get the code point that begins at offset `offset`
|
|
494
|
+
*/
|
|
495
|
+
export function getNextCodePoint(str: string, len: number, offset: number): number {
|
|
496
|
+
const charCode = str.charCodeAt(offset);
|
|
497
|
+
if (isHighSurrogate(charCode) && offset + 1 < len) {
|
|
498
|
+
const nextCharCode = str.charCodeAt(offset + 1);
|
|
499
|
+
if (isLowSurrogate(nextCharCode)) {
|
|
500
|
+
return computeCodePoint(charCode, nextCharCode);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return charCode;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* get the code point that ends right before offset `offset`
|
|
508
|
+
*/
|
|
509
|
+
function getPrevCodePoint(str: string, offset: number): number {
|
|
510
|
+
const charCode = str.charCodeAt(offset - 1);
|
|
511
|
+
if (isLowSurrogate(charCode) && offset > 1) {
|
|
512
|
+
const prevCharCode = str.charCodeAt(offset - 2);
|
|
513
|
+
if (isHighSurrogate(prevCharCode)) {
|
|
514
|
+
return computeCodePoint(prevCharCode, charCode);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return charCode;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export class CodePointIterator {
|
|
521
|
+
|
|
522
|
+
private readonly _str: string;
|
|
523
|
+
private readonly _len: number;
|
|
524
|
+
private _offset: number;
|
|
525
|
+
|
|
526
|
+
public get offset(): number {
|
|
527
|
+
return this._offset;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
constructor(str: string, offset: number = 0) {
|
|
531
|
+
this._str = str;
|
|
532
|
+
this._len = str.length;
|
|
533
|
+
this._offset = offset;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
public setOffset(offset: number): void {
|
|
537
|
+
this._offset = offset;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
public prevCodePoint(): number {
|
|
541
|
+
const codePoint = getPrevCodePoint(this._str, this._offset);
|
|
542
|
+
this._offset -= (codePoint >= Constants.UNICODE_SUPPLEMENTARY_PLANE_BEGIN ? 2 : 1);
|
|
543
|
+
return codePoint;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
public nextCodePoint(): number {
|
|
547
|
+
const codePoint = getNextCodePoint(this._str, this._len, this._offset);
|
|
548
|
+
this._offset += (codePoint >= Constants.UNICODE_SUPPLEMENTARY_PLANE_BEGIN ? 2 : 1);
|
|
549
|
+
return codePoint;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
public eol(): boolean {
|
|
553
|
+
return (this._offset >= this._len);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export const noBreakWhitespace = '\xa0';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Can be passed into the Delayed to defer using a microtask
|
|
8
|
+
* */
|
|
9
|
+
export const MicrotaskDelay = Symbol('MicrotaskDelay');
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
|
|
6
|
+
export const enum Constants {
|
|
7
|
+
/**
|
|
8
|
+
* MAX SMI (SMall Integer) as defined in v8.
|
|
9
|
+
* one bit is lost for boxing/unboxing flag.
|
|
10
|
+
* one bit is lost for sign flag.
|
|
11
|
+
* See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values
|
|
12
|
+
*/
|
|
13
|
+
MAX_SAFE_SMALL_INTEGER = 1 << 30,
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* MIN SMI (SMall Integer) as defined in v8.
|
|
17
|
+
* one bit is lost for boxing/unboxing flag.
|
|
18
|
+
* one bit is lost for sign flag.
|
|
19
|
+
* See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values
|
|
20
|
+
*/
|
|
21
|
+
MIN_SAFE_SMALL_INTEGER = -(1 << 30),
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Max unsigned integer that fits on 8 bits.
|
|
25
|
+
*/
|
|
26
|
+
MAX_UINT_8 = 255, // 2^8 - 1
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Max unsigned integer that fits on 16 bits.
|
|
30
|
+
*/
|
|
31
|
+
MAX_UINT_16 = 65535, // 2^16 - 1
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Max unsigned integer that fits on 32 bits.
|
|
35
|
+
*/
|
|
36
|
+
MAX_UINT_32 = 4294967295, // 2^32 - 1
|
|
37
|
+
|
|
38
|
+
UNICODE_SUPPLEMENTARY_PLANE_BEGIN = 0x010000
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function toUint8(v: number): number {
|
|
42
|
+
if (v < 0) {
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
if (v > Constants.MAX_UINT_8) {
|
|
46
|
+
return Constants.MAX_UINT_8;
|
|
47
|
+
}
|
|
48
|
+
return v | 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function toUint32(v: number): number {
|
|
52
|
+
if (v < 0) {
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (v > Constants.MAX_UINT_32) {
|
|
56
|
+
return Constants.MAX_UINT_32;
|
|
57
|
+
}
|
|
58
|
+
return v | 0;
|
|
59
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
|
|
6
|
+
export interface ILocalizeInfo {
|
|
7
|
+
key: string;
|
|
8
|
+
comment: string[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function localize(info: ILocalizeInfo | string, message: string, ...args: (string | number | boolean | undefined | null)[]): string {
|
|
12
|
+
return message;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface INLSLanguagePackConfiguration {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The path to the translations config file that contains pointers to
|
|
19
|
+
* all message bundles for `main` and extensions.
|
|
20
|
+
*/
|
|
21
|
+
readonly translationsConfigFile: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The path to the file containing the translations for this language
|
|
25
|
+
* pack as flat string array.
|
|
26
|
+
*/
|
|
27
|
+
readonly messagesFile: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The path to the file that can be used to signal a corrupt language
|
|
31
|
+
* pack, for example when reading the `messagesFile` fails. This will
|
|
32
|
+
* instruct the application to re-create the cache on next startup.
|
|
33
|
+
*/
|
|
34
|
+
readonly corruptMarkerFile: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface INLSConfiguration {
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Locale as defined in `argv.json` or `app.getLocale()`.
|
|
41
|
+
*/
|
|
42
|
+
readonly userLocale: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Locale as defined by the OS (e.g. `app.getPreferredSystemLanguages()`).
|
|
46
|
+
*/
|
|
47
|
+
readonly osLocale: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The actual language of the UI that ends up being used considering `userLocale`
|
|
51
|
+
* and `osLocale`.
|
|
52
|
+
*/
|
|
53
|
+
readonly resolvedLanguage: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Defined if a language pack is used that is not the
|
|
57
|
+
* default english language pack. This requires a language
|
|
58
|
+
* pack to be installed as extension.
|
|
59
|
+
*/
|
|
60
|
+
readonly languagePack?: INLSLanguagePackConfiguration;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The path to the file containing the default english messages
|
|
64
|
+
* as flat string array. The file is only present in built
|
|
65
|
+
* versions of the application.
|
|
66
|
+
*/
|
|
67
|
+
readonly defaultMessagesFile: string;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Below properties are deprecated and only there to continue support
|
|
71
|
+
* for `vscode-nls` module that depends on them.
|
|
72
|
+
* Refs https://github.com/microsoft/vscode-nls/blob/main/src/node/main.ts#L36-L46
|
|
73
|
+
*/
|
|
74
|
+
/** @deprecated */
|
|
75
|
+
readonly locale: string;
|
|
76
|
+
/** @deprecated */
|
|
77
|
+
readonly availableLanguages: Record<string, string>;
|
|
78
|
+
/** @deprecated */
|
|
79
|
+
readonly _languagePackSupport?: boolean;
|
|
80
|
+
/** @deprecated */
|
|
81
|
+
readonly _languagePackId?: string;
|
|
82
|
+
/** @deprecated */
|
|
83
|
+
readonly _translationsConfigFile?: string;
|
|
84
|
+
/** @deprecated */
|
|
85
|
+
readonly _cacheRoot?: string;
|
|
86
|
+
/** @deprecated */
|
|
87
|
+
readonly _resolvedLanguagePackCoreLocation?: string;
|
|
88
|
+
/** @deprecated */
|
|
89
|
+
readonly _corruptedFile?: string;
|
|
90
|
+
}
|