@opensumi/ide-core-common 2.21.13 → 2.22.0

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.
Files changed (159) hide show
  1. package/lib/command.d.ts +15 -5
  2. package/lib/command.d.ts.map +1 -1
  3. package/lib/command.js +11 -1
  4. package/lib/command.js.map +1 -1
  5. package/lib/const/application.d.ts +6 -1
  6. package/lib/const/application.d.ts.map +1 -1
  7. package/lib/const/application.js +8 -3
  8. package/lib/const/application.js.map +1 -1
  9. package/lib/declare.d.ts +2 -2
  10. package/lib/declare.d.ts.map +1 -1
  11. package/lib/editor.d.ts +4 -0
  12. package/lib/editor.d.ts.map +1 -1
  13. package/lib/electron.d.ts +1 -1
  14. package/lib/electron.d.ts.map +1 -1
  15. package/lib/event-bus/event-bus-types.d.ts +1 -1
  16. package/lib/event-bus/event-bus-types.d.ts.map +1 -1
  17. package/lib/event-bus/event-bus.js.map +1 -1
  18. package/lib/event-bus/event-decorator.js.map +1 -1
  19. package/lib/extension.schema.d.ts +1 -1
  20. package/lib/extension.schema.d.ts.map +1 -1
  21. package/lib/hash-calculate/WASMInterface.d.ts +2 -2
  22. package/lib/hash-calculate/WASMInterface.d.ts.map +1 -1
  23. package/lib/hash-calculate/hash-calculate.js.map +1 -1
  24. package/lib/hash-calculate/util.d.ts +2 -2
  25. package/lib/hash-calculate/util.d.ts.map +1 -1
  26. package/lib/json-schema.d.ts +9 -0
  27. package/lib/json-schema.d.ts.map +1 -1
  28. package/lib/keyboard/keymap.d.ts +1 -1
  29. package/lib/keyboard/keymap.d.ts.map +1 -1
  30. package/lib/localize.d.ts +1 -1
  31. package/lib/localize.d.ts.map +1 -1
  32. package/lib/log.d.ts +2 -2
  33. package/lib/log.d.ts.map +1 -1
  34. package/lib/mime.d.ts +6 -6
  35. package/lib/module.js.map +1 -1
  36. package/lib/preferences/preference-schema.d.ts +13 -3
  37. package/lib/preferences/preference-schema.d.ts.map +1 -1
  38. package/lib/preferences/preference-schema.js +11 -1
  39. package/lib/preferences/preference-schema.js.map +1 -1
  40. package/lib/preferences/preference-scope.d.ts +8 -1
  41. package/lib/preferences/preference-scope.d.ts.map +1 -1
  42. package/lib/preferences/preference-scope.js +11 -2
  43. package/lib/preferences/preference-scope.js.map +1 -1
  44. package/lib/problem-matcher.d.ts +1 -1
  45. package/lib/problem-matcher.d.ts.map +1 -1
  46. package/lib/problem-matcher.js.map +1 -1
  47. package/lib/problem-pattern.d.ts +4 -2
  48. package/lib/problem-pattern.d.ts.map +1 -1
  49. package/lib/problem-pattern.js +24 -1
  50. package/lib/problem-pattern.js.map +1 -1
  51. package/lib/reference.d.ts +2 -1
  52. package/lib/reference.d.ts.map +1 -1
  53. package/lib/reference.js +11 -6
  54. package/lib/reference.js.map +1 -1
  55. package/lib/reporter.js.map +1 -1
  56. package/lib/storage.d.ts +1 -1
  57. package/lib/storage.d.ts.map +1 -1
  58. package/lib/storage.js.map +1 -1
  59. package/lib/task-definition.js.map +1 -1
  60. package/lib/types/common.d.ts +1 -1
  61. package/lib/types/common.d.ts.map +1 -1
  62. package/lib/types/editor.d.ts +2 -2
  63. package/lib/types/editor.d.ts.map +1 -1
  64. package/lib/types/file-watch.d.ts +1 -1
  65. package/lib/types/file-watch.d.ts.map +1 -1
  66. package/lib/types/markers/markers-manager.d.ts.map +1 -1
  67. package/lib/types/markers/markers-manager.js +4 -10
  68. package/lib/types/markers/markers-manager.js.map +1 -1
  69. package/lib/types/markers/markers.d.ts +2 -0
  70. package/lib/types/markers/markers.d.ts.map +1 -1
  71. package/lib/types/markers/markers.js.map +1 -1
  72. package/package.json +7 -6
  73. package/src/LifeCyclePhase.ts +6 -0
  74. package/src/application-error.ts +77 -0
  75. package/src/application-props.ts +28 -0
  76. package/src/application.lifecycle.ts +15 -0
  77. package/src/browser-fs/ensure-dir.ts +46 -0
  78. package/src/browser-fs/util.ts +52 -0
  79. package/src/clipboard.ts +31 -0
  80. package/src/command.ts +726 -0
  81. package/src/commands/terminal.ts +0 -0
  82. package/src/comparers.ts +152 -0
  83. package/src/connection.ts +7 -0
  84. package/src/const/application.ts +11 -0
  85. package/src/const/index.ts +1 -0
  86. package/src/contribution-provider.ts +47 -0
  87. package/src/credential.ts +21 -0
  88. package/src/crypto.ts +8 -0
  89. package/src/declare.ts +3 -0
  90. package/src/di-helper/domain-helper.ts +48 -0
  91. package/src/di-helper/index.ts +1 -0
  92. package/src/editor.ts +6 -0
  93. package/src/electron.ts +168 -0
  94. package/src/env.ts +1 -0
  95. package/src/event-bus/basic-event.ts +3 -0
  96. package/src/event-bus/event-bus-types.ts +68 -0
  97. package/src/event-bus/event-bus.ts +57 -0
  98. package/src/event-bus/event-decorator.ts +32 -0
  99. package/src/event-bus/index.ts +4 -0
  100. package/src/extension.schema.ts +16 -0
  101. package/src/hash-calculate/WASMInterface.ts +266 -0
  102. package/src/hash-calculate/hash-calculate.ts +53 -0
  103. package/src/hash-calculate/lockedCreate.ts +17 -0
  104. package/src/hash-calculate/md5.wasm.json +1 -0
  105. package/src/hash-calculate/mutex.ts +30 -0
  106. package/src/hash-calculate/util.ts +190 -0
  107. package/src/id-generator.ts +15 -0
  108. package/src/index.ts +39 -0
  109. package/src/json-schema.ts +80 -0
  110. package/src/keyboard/index.ts +2 -0
  111. package/src/keyboard/keyboard-layout-provider.ts +46 -0
  112. package/src/keyboard/keymap.ts +224 -0
  113. package/src/line-text.ts +93 -0
  114. package/src/localize.ts +203 -0
  115. package/src/log.ts +338 -0
  116. package/src/markdown.ts +8 -0
  117. package/src/menu.ts +31 -0
  118. package/src/mime.ts +8 -0
  119. package/src/mocks/electron/browserMock.ts +10 -0
  120. package/src/mocks/electron/ipcRenderer.ts +30 -0
  121. package/src/module.ts +31 -0
  122. package/src/network.ts +47 -0
  123. package/src/node/cli.ts +5 -0
  124. package/src/node/port.ts +134 -0
  125. package/src/preferences/index.ts +2 -0
  126. package/src/preferences/preference-schema.ts +122 -0
  127. package/src/preferences/preference-scope.ts +65 -0
  128. package/src/problem-matcher.ts +389 -0
  129. package/src/problem-pattern.ts +574 -0
  130. package/src/range.ts +24 -0
  131. package/src/reference.ts +141 -0
  132. package/src/reporter.ts +64 -0
  133. package/src/settings/general.ts +5 -0
  134. package/src/settings/index.ts +3 -0
  135. package/src/settings/search.ts +7 -0
  136. package/src/settings/terminal.ts +9 -0
  137. package/src/storage.ts +99 -0
  138. package/src/task-definition.ts +172 -0
  139. package/src/theme.ts +7 -0
  140. package/src/types/accessibility.ts +4 -0
  141. package/src/types/application.ts +14 -0
  142. package/src/types/authentication.ts +120 -0
  143. package/src/types/common.ts +14 -0
  144. package/src/types/dnd.ts +8 -0
  145. package/src/types/editor.ts +246 -0
  146. package/src/types/extension.ts +96 -0
  147. package/src/types/file-watch.ts +100 -0
  148. package/src/types/file.ts +262 -0
  149. package/src/types/index.ts +15 -0
  150. package/src/types/markdown.ts +10 -0
  151. package/src/types/markers/index.ts +2 -0
  152. package/src/types/markers/markers-manager.ts +392 -0
  153. package/src/types/markers/markers.ts +125 -0
  154. package/src/types/message.ts +6 -0
  155. package/src/types/reporter.ts +96 -0
  156. package/src/types/statusbar.ts +6 -0
  157. package/src/types/string.ts +3 -0
  158. package/src/utils/index.ts +1 -0
  159. package/src/utils/ipc.ts +28 -0
@@ -0,0 +1,80 @@
1
+ export interface IJSONSchema {
2
+ id?: string;
3
+ $id?: string;
4
+ $schema?: string;
5
+ type?: string | string[];
6
+ title?: string;
7
+ default?: any;
8
+ definitions?: IJSONSchemaMap;
9
+ description?: string;
10
+ properties?: IJSONSchemaMap;
11
+ patternProperties?: IJSONSchemaMap;
12
+ additionalProperties?: boolean | IJSONSchema;
13
+ minProperties?: number;
14
+ maxProperties?: number;
15
+ dependencies?: IJSONSchemaMap | { [prop: string]: string[] };
16
+ items?: IJSONSchema | IJSONSchema[];
17
+ minItems?: number;
18
+ maxItems?: number;
19
+ uniqueItems?: boolean;
20
+ additionalItems?: boolean | IJSONSchema;
21
+ pattern?: string;
22
+ minLength?: number;
23
+ maxLength?: number;
24
+ minimum?: number;
25
+ maximum?: number;
26
+ exclusiveMinimum?: boolean | number;
27
+ exclusiveMaximum?: boolean | number;
28
+ multipleOf?: number;
29
+ required?: string[];
30
+ $ref?: string;
31
+ anyOf?: IJSONSchema[];
32
+ allOf?: IJSONSchema[];
33
+ oneOf?: IJSONSchema[];
34
+ not?: IJSONSchema;
35
+ enum?: any[];
36
+ format?: string;
37
+
38
+ // schema draft 06
39
+ const?: any;
40
+ contains?: IJSONSchema;
41
+ propertyNames?: IJSONSchema;
42
+
43
+ // schema draft 07
44
+ $comment?: string;
45
+ if?: IJSONSchema;
46
+ then?: IJSONSchema;
47
+ else?: IJSONSchema;
48
+
49
+ // VSCode extensions
50
+ defaultSnippets?: IJSONSchemaSnippet[]; // VSCode extension
51
+ errorMessage?: string; // VSCode extension
52
+ patternErrorMessage?: string; // VSCode extension
53
+ deprecationMessage?: string; // VSCode extension
54
+ enumDescriptions?: string[]; // VSCode extension
55
+ markdownEnumDescriptions?: string[]; // VSCode extension
56
+ markdownDescription?: string; // VSCode extension
57
+ doNotSuggest?: boolean; // VSCode extension
58
+ allowComments?: boolean; // VSCode extension
59
+ }
60
+
61
+ export interface IJSONSchemaMap {
62
+ [name: string]: IJSONSchema;
63
+ }
64
+
65
+ export interface IJSONSchemaSnippet {
66
+ label?: string;
67
+ description?: string;
68
+ body?: any; // a object that will be JSON stringified
69
+ bodyText?: string; // an already stringified JSON object that can contain new lines (\n) and tabs (\t)
70
+ }
71
+
72
+ export const enum CodeSchemaId {
73
+ defaultSettings = 'vscode://schemas/settings/default',
74
+ userSettings = 'vscode://schemas/settings/user',
75
+ machineSettings = 'vscode://schemas/settings/machine',
76
+ workspaceSettings = 'vscode://schemas/settings/workspace',
77
+ folderSettings = 'vscode://schemas/settings/folder',
78
+ launch = 'vscode://schemas/launch',
79
+ tasks = 'vscode://schemas/tasks',
80
+ }
@@ -0,0 +1,2 @@
1
+ export * from './keymap';
2
+ export * from './keyboard-layout-provider';
@@ -0,0 +1,46 @@
1
+ /** ******************************************************************************
2
+ * Copyright (C) 2018 Red Hat, Inc. and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+ // Some code copied and modified from https://github.com/eclipse-theia/theia/tree/v1.14.0/packages/core/src/browser/keyboard/browser-keyboard-layout-provider.ts
17
+
18
+ import { Event } from '@opensumi/ide-utils';
19
+
20
+ import { KeymapInfo } from './keymap';
21
+
22
+ export const keyboardPath = '/services/keyboard';
23
+
24
+ export const KeyboardNativeLayoutService = Symbol('KeyboardNativeLayoutService');
25
+
26
+ export interface KeyboardNativeLayoutService {
27
+ getNativeLayout(): Promise<KeymapInfo | void>;
28
+ allLayoutData: KeymapInfo[];
29
+ currentLayoutData: KeymapInfo | null;
30
+ currentLayoutSource: string;
31
+ setLayoutData(layout: KeymapInfo | 'autodetect'): Promise<KeymapInfo | null>;
32
+ }
33
+
34
+ export const KeyboardLayoutChangeNotifierService = Symbol('KeyboardLayoutChangeNotifierService');
35
+
36
+ export interface KeyboardLayoutChangeNotifierService {
37
+ onDidChangeNativeLayout: Event<KeymapInfo>;
38
+ }
39
+
40
+ export interface KeyValidationInput {
41
+ code: string;
42
+ character: string;
43
+ shiftKey?: boolean;
44
+ ctrlKey?: boolean;
45
+ altKey?: boolean;
46
+ }
@@ -0,0 +1,224 @@
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 { isLinux, isWindows } from '@opensumi/ide-utils';
7
+
8
+ // https://github.com/microsoft/node-native-keymap/blob/master/index.d.ts
9
+
10
+ export interface IWindowsKeyboardMapping {
11
+ [code: string]: IWindowsKeyMapping;
12
+ }
13
+
14
+ export interface IWindowsKeyMapping {
15
+ vkey: string;
16
+ value: string;
17
+ withShift: string;
18
+ withAltGr: string;
19
+ withShiftAltGr: string;
20
+ }
21
+
22
+ export interface IWindowsKeyboardLayoutInfo {
23
+ name: string;
24
+ id: string;
25
+ text: string;
26
+ }
27
+
28
+ export interface ILinuxKeyboardLayoutInfo {
29
+ model: string;
30
+ layout: string;
31
+ variant: string;
32
+ options: string;
33
+ rules: string;
34
+ }
35
+
36
+ export interface IMacKeyboardLayoutInfo {
37
+ id: string;
38
+ localizedName?: string;
39
+ lang: string;
40
+ }
41
+
42
+ export interface IWindowsKeyboardLayoutInfo {
43
+ name: string;
44
+ id: string;
45
+ text: string;
46
+ }
47
+
48
+ export type IKeyboardLayoutInfo = (IWindowsKeyboardLayoutInfo | ILinuxKeyboardLayoutInfo | IMacKeyboardLayoutInfo) & {
49
+ isUserKeyboardLayout?: boolean;
50
+ isUSStandard?: true;
51
+ };
52
+
53
+ export interface ISerializedMapping {
54
+ [key: string]: (string | number)[];
55
+ }
56
+
57
+ export interface IKeymapInfo {
58
+ layout: IKeyboardLayoutInfo;
59
+ secondaryLayouts: IKeyboardLayoutInfo[];
60
+ mapping: ISerializedMapping;
61
+ isUserKeyboardLayout?: boolean;
62
+ }
63
+
64
+ export interface IRawMixedKeyboardMapping {
65
+ [key: string]: {
66
+ value: string;
67
+ withShift: string;
68
+ withAltGr: string;
69
+ withShiftAltGr: string;
70
+ valueIsDeadKey?: boolean;
71
+ withShiftIsDeadKey?: boolean;
72
+ withAltGrIsDeadKey?: boolean;
73
+ withShiftAltGrIsDeadKey?: boolean;
74
+ };
75
+ }
76
+
77
+ function deserializeMapping(serializedMapping: ISerializedMapping) {
78
+ const mapping = serializedMapping;
79
+
80
+ const ret: { [key: string]: any } = {};
81
+ // eslint-disable-next-line guard-for-in
82
+ for (const key in mapping) {
83
+ const result: (string | number)[] = mapping[key];
84
+ if (result.length) {
85
+ const value = result[0];
86
+ const withShift = result[1];
87
+ const withAltGr = result[2];
88
+ const withShiftAltGr = result[3];
89
+ const mask = Number(result[4]);
90
+ const vkey = result.length === 6 ? result[5] : undefined;
91
+ ret[key] = {
92
+ value,
93
+ vkey,
94
+ withShift,
95
+ withAltGr,
96
+ withShiftAltGr,
97
+ valueIsDeadKey: (mask & 1) > 0,
98
+ withShiftIsDeadKey: (mask & 2) > 0,
99
+ withAltGrIsDeadKey: (mask & 4) > 0,
100
+ withShiftAltGrIsDeadKey: (mask & 8) > 0,
101
+ };
102
+ } else {
103
+ ret[key] = {
104
+ value: '',
105
+ valueIsDeadKey: false,
106
+ withShift: '',
107
+ withShiftIsDeadKey: false,
108
+ withAltGr: '',
109
+ withAltGrIsDeadKey: false,
110
+ withShiftAltGr: '',
111
+ withShiftAltGrIsDeadKey: false,
112
+ };
113
+ }
114
+ }
115
+
116
+ return ret;
117
+ }
118
+
119
+ export function getKeyboardLayoutId(layout: IKeyboardLayoutInfo): string {
120
+ if ((layout as IWindowsKeyboardLayoutInfo).name) {
121
+ return (layout as IWindowsKeyboardLayoutInfo).name;
122
+ }
123
+
124
+ if ((layout as IMacKeyboardLayoutInfo).id) {
125
+ return (layout as IMacKeyboardLayoutInfo).id;
126
+ }
127
+ return (layout as ILinuxKeyboardLayoutInfo).layout;
128
+ }
129
+
130
+ export class KeymapInfo {
131
+ mapping: IRawMixedKeyboardMapping;
132
+ isUserKeyboardLayout: boolean;
133
+
134
+ constructor(
135
+ public layout: IKeyboardLayoutInfo,
136
+ public secondaryLayouts: IKeyboardLayoutInfo[],
137
+ keyboardMapping: ISerializedMapping,
138
+ isUserKeyboardLayout?: boolean,
139
+ ) {
140
+ this.mapping = deserializeMapping(keyboardMapping);
141
+ this.isUserKeyboardLayout = !!isUserKeyboardLayout;
142
+ this.layout.isUserKeyboardLayout = !!isUserKeyboardLayout;
143
+ }
144
+
145
+ static createKeyboardLayoutFromDebugInfo(
146
+ layout: IKeyboardLayoutInfo,
147
+ value: IRawMixedKeyboardMapping,
148
+ isUserKeyboardLayout?: boolean,
149
+ ): KeymapInfo {
150
+ const keyboardLayoutInfo = new KeymapInfo(layout, [], {}, true);
151
+ keyboardLayoutInfo.mapping = value;
152
+ return keyboardLayoutInfo;
153
+ }
154
+
155
+ update(other: KeymapInfo) {
156
+ this.layout = other.layout;
157
+ this.secondaryLayouts = other.secondaryLayouts;
158
+ this.mapping = other.mapping;
159
+ this.isUserKeyboardLayout = other.isUserKeyboardLayout;
160
+ this.layout.isUserKeyboardLayout = other.isUserKeyboardLayout;
161
+ }
162
+
163
+ getScore(other: IRawMixedKeyboardMapping): number {
164
+ let score = 0;
165
+ for (const key in other) {
166
+ if (isWindows && (key === 'Backslash' || key === 'KeyQ')) {
167
+ // keymap from Chromium is probably wrong.
168
+ continue;
169
+ }
170
+
171
+ if (isLinux && (key === 'Backspace' || key === 'Escape')) {
172
+ // native keymap doesn't align with keyboard event
173
+ continue;
174
+ }
175
+
176
+ const currentMapping = this.mapping[key];
177
+
178
+ if (currentMapping === undefined) {
179
+ score -= 1;
180
+ }
181
+
182
+ const otherMapping = other[key];
183
+
184
+ if (currentMapping && otherMapping && currentMapping.value !== otherMapping.value) {
185
+ score -= 1;
186
+ }
187
+ }
188
+
189
+ return score;
190
+ }
191
+
192
+ equal(other: KeymapInfo): boolean {
193
+ if (this.isUserKeyboardLayout !== other.isUserKeyboardLayout) {
194
+ return false;
195
+ }
196
+
197
+ if (getKeyboardLayoutId(this.layout) !== getKeyboardLayoutId(other.layout)) {
198
+ return false;
199
+ }
200
+
201
+ return this.fuzzyEqual(other.mapping);
202
+ }
203
+
204
+ fuzzyEqual(other: IRawMixedKeyboardMapping): boolean {
205
+ for (const key in other) {
206
+ if (isWindows && (key === 'Backslash' || key === 'KeyQ')) {
207
+ // keymap from Chromium is probably wrong.
208
+ continue;
209
+ }
210
+ if (this.mapping[key] === undefined) {
211
+ return false;
212
+ }
213
+
214
+ const currentMapping = this.mapping[key];
215
+ const otherMapping = other[key];
216
+
217
+ if (currentMapping.value !== otherMapping.value) {
218
+ return false;
219
+ }
220
+ }
221
+
222
+ return true;
223
+ }
224
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * 用于实现效率更高的编辑操作
3
+ */
4
+
5
+ import { IRange, IPosition, IEditOperation } from './types/editor';
6
+
7
+ export class BasicTextLines {
8
+ constructor(protected readonly _lines: string[], protected _eol: '\n' | '\r\n') {}
9
+
10
+ getContent() {
11
+ return this._lines.join(this._eol);
12
+ }
13
+
14
+ private _setLineText(lineIndex: number, newValue: string): void {
15
+ this._lines[lineIndex] = newValue;
16
+ }
17
+
18
+ public acceptEol(eol: '\n' | '\r\n') {
19
+ this._eol = eol;
20
+ }
21
+
22
+ public acceptChange(change: IEditOperation) {
23
+ this._acceptDeleteRange(change.range);
24
+ this._acceptInsertText(
25
+ { lineNumber: change.range.startLineNumber, column: change.range.startColumn },
26
+ change.text || '',
27
+ );
28
+ }
29
+
30
+ private _getLineContent(index: number): string {
31
+ return this._lines[index] || '';
32
+ }
33
+
34
+ private _acceptDeleteRange(range: IRange): void {
35
+ if (range.startLineNumber === range.endLineNumber) {
36
+ if (range.startColumn === range.endColumn) {
37
+ // Nothing to delete
38
+ return;
39
+ }
40
+ // Delete text on the affected line
41
+ this._setLineText(
42
+ range.startLineNumber - 1,
43
+ this._getLineContent(range.startLineNumber - 1).substring(0, range.startColumn - 1) +
44
+ this._getLineContent(range.startLineNumber - 1).substring(range.endColumn - 1),
45
+ );
46
+ return;
47
+ }
48
+
49
+ // Take remaining text on last line and append it to remaining text on first line
50
+ this._setLineText(
51
+ range.startLineNumber - 1,
52
+ this._getLineContent(range.startLineNumber - 1).substring(0, range.startColumn - 1) +
53
+ this._getLineContent(range.endLineNumber - 1).substring(range.endColumn - 1),
54
+ );
55
+
56
+ // Delete middle lines
57
+ this._lines.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber);
58
+ }
59
+
60
+ private _acceptInsertText(position: IPosition, insertText: string): void {
61
+ if (insertText.length === 0) {
62
+ // Nothing to insert
63
+ return;
64
+ }
65
+ const insertLines = insertText.split(/\r\n|\r|\n/);
66
+ if (insertLines.length === 1) {
67
+ // Inserting text on one line
68
+ this._setLineText(
69
+ position.lineNumber - 1,
70
+ this._getLineContent(position.lineNumber - 1).substring(0, position.column - 1) +
71
+ insertLines[0] +
72
+ this._getLineContent(position.lineNumber - 1).substring(position.column - 1),
73
+ );
74
+ return;
75
+ }
76
+
77
+ // Append overflowing text from first line to the end of text to insert
78
+ insertLines[insertLines.length - 1] += this._getLineContent(position.lineNumber - 1).substring(position.column - 1);
79
+
80
+ // Delete overflowing text from first line and insert text on first line
81
+ this._setLineText(
82
+ position.lineNumber - 1,
83
+ this._getLineContent(position.lineNumber - 1).substring(0, position.column - 1) + insertLines[0],
84
+ );
85
+
86
+ // Insert new lines & store lengths
87
+ const newLengths = new Uint32Array(insertLines.length - 1);
88
+ for (let i = 1; i < insertLines.length; i++) {
89
+ this._lines.splice(position.lineNumber + i - 1, 0, insertLines[i]);
90
+ newLengths[i - 1] = insertLines[i].length + this._eol.length;
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,203 @@
1
+ import { strings, CaseInsensitiveMap } from '@opensumi/ide-utils';
2
+
3
+ const { format, mnemonicButtonLabel } = strings;
4
+
5
+ export type ILocalizationKey = string; // ts不支持symbol作为key
6
+
7
+ let _currentLanguageId = 'zh-CN';
8
+
9
+ const localizationRegistryMap = new CaseInsensitiveMap<string, LocalizationRegistry>();
10
+
11
+ export function localize(
12
+ symbol: ILocalizationKey,
13
+ defaultMessage?: string | undefined,
14
+ scope = 'host',
15
+ language = _currentLanguageId,
16
+ ): string {
17
+ const localizationRegistry = getLocalizationRegistry(scope);
18
+ return localizationRegistry.getLocalizeString(symbol, defaultMessage, language);
19
+ }
20
+
21
+ export function formatLocalize(symbol: ILocalizationKey, ...args: any) {
22
+ return format(localize(symbol), ...args);
23
+ }
24
+
25
+ export function registerLocalizationBundle(bundle: ILocalizationBundle, scope = 'host') {
26
+ return getLocalizationRegistry(scope).registerLocalizationBundle(bundle);
27
+ }
28
+
29
+ interface IExtensionLocalizationValue {
30
+ message: string;
31
+ comment: string;
32
+ }
33
+
34
+ export interface IExtensionLocalizationContents {
35
+ [key: string]: string | IExtensionLocalizationValue;
36
+ }
37
+
38
+ export interface ILocalizationBundle extends ILocalizationInfo {
39
+ contents: IExtensionLocalizationContents;
40
+ }
41
+
42
+ export interface ILocalizationInfo {
43
+ languageId: string;
44
+ languageName: string;
45
+ localizedLanguageName: string;
46
+ }
47
+
48
+ export interface ILocalizationContents {
49
+ [key: string]: string;
50
+ }
51
+
52
+ interface ILocalizationRegistry {
53
+ registerLocalizationBundle(bundle: ILocalizationBundle): void;
54
+
55
+ getLocalizeString(symbol: ILocalizationKey, defaultLabel?: string, languageId?: string): string;
56
+
57
+ getAllLanguages(): ILocalizationInfo[];
58
+ }
59
+
60
+ function isExtensionLocalizationValue(thing: any): thing is IExtensionLocalizationValue {
61
+ return typeof thing === 'object' && thing.message;
62
+ }
63
+
64
+ class LocalizationRegistry implements ILocalizationRegistry {
65
+ private localizationMap = new CaseInsensitiveMap<string, ILocalizationContents>();
66
+
67
+ public readonly localizationInfo = new CaseInsensitiveMap<string, ILocalizationInfo>();
68
+
69
+ registerLocalizationBundle(bundle: ILocalizationBundle): void {
70
+ const languageId = bundle.languageId;
71
+ if (!languageId) {
72
+ return;
73
+ }
74
+ const existingMessages = this.getContents(languageId);
75
+ Object.keys(bundle.contents).forEach((key: ILocalizationKey) => {
76
+ const rawContent = bundle.contents[key];
77
+ let content: string;
78
+ if (isExtensionLocalizationValue(rawContent)) {
79
+ content = rawContent.message;
80
+ } else {
81
+ content = rawContent;
82
+ }
83
+ existingMessages[key] = mnemonicButtonLabel(content, true); // 暂时去除所有注记符
84
+ });
85
+ if (!this.localizationInfo.has(languageId)) {
86
+ this.localizationInfo.set(languageId, Object.assign({}, bundle, { contents: undefined }));
87
+ }
88
+ }
89
+
90
+ getLocalizeString(key: ILocalizationKey, defaultValue?: string | null, languageId = _currentLanguageId): string {
91
+ return this.getContents(languageId)[key] || this.getContents('default')[key] || defaultValue || '';
92
+ }
93
+
94
+ private getContents(languageId: string | undefined = 'zh-CN'): ILocalizationContents {
95
+ if (!languageId) {
96
+ return {};
97
+ }
98
+ if (!this.localizationMap.has(languageId)) {
99
+ this.localizationMap.set(languageId, {});
100
+ }
101
+ return this.localizationMap.get(languageId) as ILocalizationContents;
102
+ }
103
+
104
+ getAllLanguages(): ILocalizationInfo[] {
105
+ return Array.from(this.localizationInfo.values());
106
+ }
107
+ }
108
+
109
+ /**
110
+ * 获取当前语言别名,默认为中文
111
+ * TODO 临时通过 href 获取
112
+ * @returns 当前语言别名
113
+ */
114
+ export function getLanguageId(scope = 'host'): string {
115
+ return _currentLanguageId;
116
+ }
117
+
118
+ /**
119
+ * for vscode extension use.
120
+ *
121
+ * vscode consider that `en` and `en-us` are the same language(you can search for `en-us` in their code base).
122
+ * and their default language is `en`, so we should transform the language id to the vscode language id.
123
+ *
124
+ * and vscode fetch the language id from the browser (`navigator.language`) or electron's [`app.getLocale()`](https://www.electronjs.org/zh/docs/latest/api/app#appgetlocale).
125
+ * they both using Chromium's l10n_util library. Possible values are here: https://source.chromium.org/chromium/chromium/src/+/master:ui/base/l10n/l10n_util.cc
126
+ *
127
+ * The language used for the user interface. The format of the string is all lower case (e.g. zh-tw for Traditional Chinese)
128
+ * see: [language](https://github.com/microsoft/vscode/blob/32b031eeefc4fd27a21659d35070967bfe965bcc/src/vs/base/common/platform.ts#L165)
129
+ */
130
+ export function getCodeLanguage(): string {
131
+ const languageId = _currentLanguageId.toLowerCase();
132
+ return (
133
+ {
134
+ 'en-us': 'en',
135
+ }[languageId] ?? languageId
136
+ );
137
+ }
138
+
139
+ export function getCurrentLanguageInfo(scope = 'host'): ILocalizationInfo {
140
+ return getLocalizationRegistry(scope).localizationInfo.get(_currentLanguageId)!;
141
+ }
142
+
143
+ export function setLanguageId(languageId: string): void {
144
+ _currentLanguageId = languageId;
145
+ }
146
+
147
+ export function getAvailableLanguages(scope = 'host'): ILocalizationInfo[] {
148
+ return getLocalizationRegistry(scope).getAllLanguages();
149
+ }
150
+
151
+ function getLocalizationRegistry(scope: string): LocalizationRegistry {
152
+ if (!localizationRegistryMap.has(scope)) {
153
+ localizationRegistryMap.set(scope, new LocalizationRegistry());
154
+ }
155
+ return localizationRegistryMap.get(scope)!;
156
+ }
157
+
158
+ /**
159
+ * 将整段字符串中所有的占位符标识的做一遍转换,
160
+ * 标识符转换失败则返回该字符串本身:
161
+ * ```js
162
+ * "%abcd%1 %1234%2".replace(/%(.*?)%/g, (c, a)=>{return c;})
163
+ * -> "%abcd%1 %1234%2"
164
+ * ```
165
+ * @param label 要转换的字段
166
+ * @param scope 默认为 host
167
+ */
168
+ export function replaceLocalizePlaceholder(label?: string, scope?: string): string | undefined {
169
+ if (label) {
170
+ return label.replace(/%(.*?)%/g, (w, p) => localize(p, w, scope).replace(/\"/g, '\\"'));
171
+ }
172
+ return label;
173
+ }
174
+
175
+ /**
176
+ * 含有占位符标识的字段转换,字段为 falsy 的时候返回该字段
177
+ * 占位符找不到时返回 fallback 值(默认为 undefined)
178
+ * @param label 要转换的字段
179
+ * @param scope 默认为 host
180
+ * @param fallback 默认为 undefined
181
+ */
182
+ export function replaceNlsField(label: string, scope: string, fallback: string, language?: string): string;
183
+ export function replaceNlsField(
184
+ label?: string,
185
+ scope?: string,
186
+ fallback?: string,
187
+ language?: string,
188
+ ): string | undefined;
189
+ export function replaceNlsField(
190
+ label?: string,
191
+ scope?: string,
192
+ fallback: string | undefined = undefined,
193
+ language = _currentLanguageId,
194
+ ): string | undefined {
195
+ if (label) {
196
+ const nlsRegex = /^%([\w\d.-]+)%$/i;
197
+ const result = nlsRegex.exec(label);
198
+ if (result) {
199
+ return localize(result[1], fallback, scope, language);
200
+ }
201
+ }
202
+ return label;
203
+ }