@lvce-editor/quick-pick-worker 1.0.1
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/LICENSE +21 -0
- package/README.md +12 -0
- package/dist/quickPickWorkerMain.js +4113 -0
- package/package.json +15 -0
|
@@ -0,0 +1,4113 @@
|
|
|
1
|
+
const EditorWorker = 99;
|
|
2
|
+
const RendererWorker = 1;
|
|
3
|
+
|
|
4
|
+
const normalizeLine = line => {
|
|
5
|
+
if (line.startsWith('Error: ')) {
|
|
6
|
+
return line.slice('Error: '.length);
|
|
7
|
+
}
|
|
8
|
+
if (line.startsWith('VError: ')) {
|
|
9
|
+
return line.slice('VError: '.length);
|
|
10
|
+
}
|
|
11
|
+
return line;
|
|
12
|
+
};
|
|
13
|
+
const getCombinedMessage = (error, message) => {
|
|
14
|
+
const stringifiedError = normalizeLine(`${error}`);
|
|
15
|
+
if (message) {
|
|
16
|
+
return `${message}: ${stringifiedError}`;
|
|
17
|
+
}
|
|
18
|
+
return stringifiedError;
|
|
19
|
+
};
|
|
20
|
+
const NewLine$2 = '\n';
|
|
21
|
+
const getNewLineIndex$1 = (string, startIndex = undefined) => {
|
|
22
|
+
return string.indexOf(NewLine$2, startIndex);
|
|
23
|
+
};
|
|
24
|
+
const mergeStacks = (parent, child) => {
|
|
25
|
+
if (!child) {
|
|
26
|
+
return parent;
|
|
27
|
+
}
|
|
28
|
+
const parentNewLineIndex = getNewLineIndex$1(parent);
|
|
29
|
+
const childNewLineIndex = getNewLineIndex$1(child);
|
|
30
|
+
if (childNewLineIndex === -1) {
|
|
31
|
+
return parent;
|
|
32
|
+
}
|
|
33
|
+
const parentFirstLine = parent.slice(0, parentNewLineIndex);
|
|
34
|
+
const childRest = child.slice(childNewLineIndex);
|
|
35
|
+
const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
|
|
36
|
+
if (parentFirstLine.includes(childFirstLine)) {
|
|
37
|
+
return parentFirstLine + childRest;
|
|
38
|
+
}
|
|
39
|
+
return child;
|
|
40
|
+
};
|
|
41
|
+
class VError extends Error {
|
|
42
|
+
constructor(error, message) {
|
|
43
|
+
const combinedMessage = getCombinedMessage(error, message);
|
|
44
|
+
super(combinedMessage);
|
|
45
|
+
this.name = 'VError';
|
|
46
|
+
if (error instanceof Error) {
|
|
47
|
+
this.stack = mergeStacks(this.stack, error.stack);
|
|
48
|
+
}
|
|
49
|
+
if (error.codeFrame) {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
this.codeFrame = error.codeFrame;
|
|
52
|
+
}
|
|
53
|
+
if (error.code) {
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
this.code = error.code;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class AssertionError extends Error {
|
|
61
|
+
constructor(message) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = 'AssertionError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const Object$1 = 1;
|
|
67
|
+
const Number$1 = 2;
|
|
68
|
+
const Array$1 = 3;
|
|
69
|
+
const String$1 = 4;
|
|
70
|
+
const Boolean$1 = 5;
|
|
71
|
+
const Function = 6;
|
|
72
|
+
const Null = 7;
|
|
73
|
+
const Unknown = 8;
|
|
74
|
+
const getType = value => {
|
|
75
|
+
switch (typeof value) {
|
|
76
|
+
case 'number':
|
|
77
|
+
return Number$1;
|
|
78
|
+
case 'function':
|
|
79
|
+
return Function;
|
|
80
|
+
case 'string':
|
|
81
|
+
return String$1;
|
|
82
|
+
case 'object':
|
|
83
|
+
if (value === null) {
|
|
84
|
+
return Null;
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
return Array$1;
|
|
88
|
+
}
|
|
89
|
+
return Object$1;
|
|
90
|
+
case 'boolean':
|
|
91
|
+
return Boolean$1;
|
|
92
|
+
default:
|
|
93
|
+
return Unknown;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const object = value => {
|
|
97
|
+
const type = getType(value);
|
|
98
|
+
if (type !== Object$1) {
|
|
99
|
+
throw new AssertionError('expected value to be of type object');
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const number = value => {
|
|
103
|
+
const type = getType(value);
|
|
104
|
+
if (type !== Number$1) {
|
|
105
|
+
throw new AssertionError('expected value to be of type number');
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const array = value => {
|
|
109
|
+
const type = getType(value);
|
|
110
|
+
if (type !== Array$1) {
|
|
111
|
+
throw new AssertionError('expected value to be of type array');
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const string = value => {
|
|
115
|
+
const type = getType(value);
|
|
116
|
+
if (type !== String$1) {
|
|
117
|
+
throw new AssertionError('expected value to be of type string');
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
class CommandNotFoundError extends Error {
|
|
122
|
+
constructor(command) {
|
|
123
|
+
super(`Command not found ${command}`);
|
|
124
|
+
this.name = 'CommandNotFoundError';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const commands = Object.create(null);
|
|
128
|
+
const register$1 = commandMap => {
|
|
129
|
+
Object.assign(commands, commandMap);
|
|
130
|
+
};
|
|
131
|
+
const getCommand = key => {
|
|
132
|
+
return commands[key];
|
|
133
|
+
};
|
|
134
|
+
const execute = (command, ...args) => {
|
|
135
|
+
const fn = getCommand(command);
|
|
136
|
+
if (!fn) {
|
|
137
|
+
throw new CommandNotFoundError(command);
|
|
138
|
+
}
|
|
139
|
+
return fn(...args);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const createMockRpc = ({
|
|
143
|
+
commandMap
|
|
144
|
+
}) => {
|
|
145
|
+
const invocations = [];
|
|
146
|
+
const invoke = (method, ...params) => {
|
|
147
|
+
invocations.push([method, ...params]);
|
|
148
|
+
const command = commandMap[method];
|
|
149
|
+
if (!command) {
|
|
150
|
+
throw new Error(`command ${method} not found`);
|
|
151
|
+
}
|
|
152
|
+
return command(...params);
|
|
153
|
+
};
|
|
154
|
+
const mockRpc = {
|
|
155
|
+
invocations,
|
|
156
|
+
invoke,
|
|
157
|
+
invokeAndTransfer: invoke
|
|
158
|
+
};
|
|
159
|
+
return mockRpc;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const rpcs = Object.create(null);
|
|
163
|
+
const set$3 = (id, rpc) => {
|
|
164
|
+
rpcs[id] = rpc;
|
|
165
|
+
};
|
|
166
|
+
const get$2 = id => {
|
|
167
|
+
return rpcs[id];
|
|
168
|
+
};
|
|
169
|
+
const remove$1 = id => {
|
|
170
|
+
delete rpcs[id];
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
174
|
+
const create$b = rpcId => {
|
|
175
|
+
return {
|
|
176
|
+
async dispose() {
|
|
177
|
+
const rpc = get$2(rpcId);
|
|
178
|
+
await rpc.dispose();
|
|
179
|
+
},
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
invoke(method, ...params) {
|
|
182
|
+
const rpc = get$2(rpcId);
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
return rpc.invoke(method, ...params);
|
|
185
|
+
},
|
|
186
|
+
// @ts-ignore
|
|
187
|
+
invokeAndTransfer(method, ...params) {
|
|
188
|
+
const rpc = get$2(rpcId);
|
|
189
|
+
// @ts-ignore
|
|
190
|
+
return rpc.invokeAndTransfer(method, ...params);
|
|
191
|
+
},
|
|
192
|
+
registerMockRpc(commandMap) {
|
|
193
|
+
const mockRpc = createMockRpc({
|
|
194
|
+
commandMap
|
|
195
|
+
});
|
|
196
|
+
set$3(rpcId, mockRpc);
|
|
197
|
+
// @ts-ignore
|
|
198
|
+
mockRpc[Symbol.dispose] = () => {
|
|
199
|
+
remove$1(rpcId);
|
|
200
|
+
};
|
|
201
|
+
// @ts-ignore
|
|
202
|
+
return mockRpc;
|
|
203
|
+
},
|
|
204
|
+
set(rpc) {
|
|
205
|
+
set$3(rpcId, rpc);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const {
|
|
211
|
+
invoke: invoke$2,
|
|
212
|
+
set: set$2
|
|
213
|
+
} = create$b(EditorWorker);
|
|
214
|
+
const getLines = async editorUid => {
|
|
215
|
+
const lines = await invoke$2('Editor.getLines2', editorUid);
|
|
216
|
+
return lines;
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const {
|
|
220
|
+
invoke: invoke$1,
|
|
221
|
+
invokeAndTransfer,
|
|
222
|
+
set: set$1
|
|
223
|
+
} = create$b(RendererWorker);
|
|
224
|
+
const sendMessagePortToEditorWorker = async (port, rpcId) => {
|
|
225
|
+
const command = 'HandleMessagePort.handleMessagePort';
|
|
226
|
+
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToEditorWorker', port, command, rpcId);
|
|
227
|
+
};
|
|
228
|
+
const setFocus = key => {
|
|
229
|
+
return invoke$1('Focus.setFocus', key);
|
|
230
|
+
};
|
|
231
|
+
const getFileIcon = async options => {
|
|
232
|
+
return invoke$1('IconTheme.getFileIcon', options);
|
|
233
|
+
};
|
|
234
|
+
const getFolderIcon = async options => {
|
|
235
|
+
return invoke$1('IconTheme.getFolderIcon', options);
|
|
236
|
+
};
|
|
237
|
+
const closeWidget$1 = async widgetId => {
|
|
238
|
+
return invoke$1('Viewlet.closeWidget', widgetId);
|
|
239
|
+
};
|
|
240
|
+
const getActiveEditorId = () => {
|
|
241
|
+
return invoke$1('GetActiveEditor.getActiveEditorId');
|
|
242
|
+
};
|
|
243
|
+
const openUri$1 = async (uri, focus, options) => {
|
|
244
|
+
await invoke$1('Main.openUri', uri, focus, options);
|
|
245
|
+
};
|
|
246
|
+
const showErrorDialog$1 = async errorInfo => {
|
|
247
|
+
await invoke$1('ErrorHandling.showErrorDialog', errorInfo);
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const closeWidget = async id => {
|
|
251
|
+
// @ts-ignore
|
|
252
|
+
await closeWidget$1(id);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const close = async state => {
|
|
256
|
+
await closeWidget(state.uid);
|
|
257
|
+
return state;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const User = 1;
|
|
261
|
+
const Script = 2;
|
|
262
|
+
|
|
263
|
+
const minimumSliderSize = 20;
|
|
264
|
+
|
|
265
|
+
const Default$1 = 0;
|
|
266
|
+
const Finished = 2;
|
|
267
|
+
|
|
268
|
+
const toCommandId = key => {
|
|
269
|
+
const dotIndex = key.indexOf('.');
|
|
270
|
+
return key.slice(dotIndex + 1);
|
|
271
|
+
};
|
|
272
|
+
const create$a = () => {
|
|
273
|
+
const states = Object.create(null);
|
|
274
|
+
const commandMapRef = {};
|
|
275
|
+
return {
|
|
276
|
+
clear() {
|
|
277
|
+
for (const key of Object.keys(states)) {
|
|
278
|
+
delete states[key];
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
diff(uid, modules, numbers) {
|
|
282
|
+
const {
|
|
283
|
+
newState,
|
|
284
|
+
oldState
|
|
285
|
+
} = states[uid];
|
|
286
|
+
const diffResult = [];
|
|
287
|
+
for (let i = 0; i < modules.length; i++) {
|
|
288
|
+
const fn = modules[i];
|
|
289
|
+
if (!fn(oldState, newState)) {
|
|
290
|
+
diffResult.push(numbers[i]);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return diffResult;
|
|
294
|
+
},
|
|
295
|
+
dispose(uid) {
|
|
296
|
+
delete states[uid];
|
|
297
|
+
},
|
|
298
|
+
get(uid) {
|
|
299
|
+
return states[uid];
|
|
300
|
+
},
|
|
301
|
+
getCommandIds() {
|
|
302
|
+
const keys = Object.keys(commandMapRef);
|
|
303
|
+
const ids = keys.map(toCommandId);
|
|
304
|
+
return ids;
|
|
305
|
+
},
|
|
306
|
+
getKeys() {
|
|
307
|
+
return Object.keys(states).map(key => {
|
|
308
|
+
return Number.parseFloat(key);
|
|
309
|
+
});
|
|
310
|
+
},
|
|
311
|
+
registerCommands(commandMap) {
|
|
312
|
+
Object.assign(commandMapRef, commandMap);
|
|
313
|
+
},
|
|
314
|
+
set(uid, oldState, newState) {
|
|
315
|
+
states[uid] = {
|
|
316
|
+
newState,
|
|
317
|
+
oldState
|
|
318
|
+
};
|
|
319
|
+
},
|
|
320
|
+
wrapCommand(fn) {
|
|
321
|
+
const wrapped = async (uid, ...args) => {
|
|
322
|
+
const {
|
|
323
|
+
newState,
|
|
324
|
+
oldState
|
|
325
|
+
} = states[uid];
|
|
326
|
+
const newerState = await fn(newState, ...args);
|
|
327
|
+
if (oldState === newerState || newState === newerState) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const latestOld = states[uid];
|
|
331
|
+
const latestNew = {
|
|
332
|
+
...latestOld.newState,
|
|
333
|
+
...newerState
|
|
334
|
+
};
|
|
335
|
+
states[uid] = {
|
|
336
|
+
newState: latestNew,
|
|
337
|
+
oldState: latestOld.oldState
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
return wrapped;
|
|
341
|
+
},
|
|
342
|
+
wrapGetter(fn) {
|
|
343
|
+
const wrapped = (uid, ...args) => {
|
|
344
|
+
const {
|
|
345
|
+
newState
|
|
346
|
+
} = states[uid];
|
|
347
|
+
return fn(newState, ...args);
|
|
348
|
+
};
|
|
349
|
+
return wrapped;
|
|
350
|
+
},
|
|
351
|
+
wrapLoadContent(fn) {
|
|
352
|
+
const wrapped = async (uid, ...args) => {
|
|
353
|
+
const {
|
|
354
|
+
newState,
|
|
355
|
+
oldState
|
|
356
|
+
} = states[uid];
|
|
357
|
+
const result = await fn(newState, ...args);
|
|
358
|
+
const {
|
|
359
|
+
error,
|
|
360
|
+
state
|
|
361
|
+
} = result;
|
|
362
|
+
if (oldState === state || newState === state) {
|
|
363
|
+
return {
|
|
364
|
+
error
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
const latestOld = states[uid];
|
|
368
|
+
const latestNew = {
|
|
369
|
+
...latestOld.newState,
|
|
370
|
+
...state
|
|
371
|
+
};
|
|
372
|
+
states[uid] = {
|
|
373
|
+
newState: latestNew,
|
|
374
|
+
oldState: latestOld.oldState
|
|
375
|
+
};
|
|
376
|
+
return {
|
|
377
|
+
error
|
|
378
|
+
};
|
|
379
|
+
};
|
|
380
|
+
return wrapped;
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const {
|
|
386
|
+
dispose: dispose$1,
|
|
387
|
+
get: get$1,
|
|
388
|
+
getCommandIds,
|
|
389
|
+
registerCommands,
|
|
390
|
+
set,
|
|
391
|
+
wrapCommand
|
|
392
|
+
} = create$a();
|
|
393
|
+
|
|
394
|
+
const create$9 = ({
|
|
395
|
+
headerHeight = 0,
|
|
396
|
+
itemHeight,
|
|
397
|
+
minimumSliderSize = 20
|
|
398
|
+
}) => {
|
|
399
|
+
return {
|
|
400
|
+
deltaY: 0,
|
|
401
|
+
finalDeltaY: 0,
|
|
402
|
+
focusedIndex: -1,
|
|
403
|
+
headerHeight,
|
|
404
|
+
itemHeight,
|
|
405
|
+
items: [],
|
|
406
|
+
maxLineY: 0,
|
|
407
|
+
minimumSliderSize,
|
|
408
|
+
minLineY: 0,
|
|
409
|
+
scrollBarActive: false,
|
|
410
|
+
scrollBarHeight: 0,
|
|
411
|
+
touchDifference: 0,
|
|
412
|
+
touchOffsetY: 0,
|
|
413
|
+
touchTimeStamp: 0
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
const getListHeight$1 = (height, headerHeight) => {
|
|
417
|
+
if (headerHeight) {
|
|
418
|
+
return height - headerHeight;
|
|
419
|
+
}
|
|
420
|
+
return headerHeight;
|
|
421
|
+
};
|
|
422
|
+
const setDeltaY = (state, deltaY) => {
|
|
423
|
+
object(state);
|
|
424
|
+
number(deltaY);
|
|
425
|
+
const {
|
|
426
|
+
headerHeight,
|
|
427
|
+
height,
|
|
428
|
+
itemHeight,
|
|
429
|
+
items
|
|
430
|
+
} = state;
|
|
431
|
+
const listHeight = getListHeight$1(height, headerHeight);
|
|
432
|
+
const itemsLength = items.length;
|
|
433
|
+
const finalDeltaY = itemsLength * itemHeight - listHeight;
|
|
434
|
+
if (deltaY < 0) {
|
|
435
|
+
deltaY = 0;
|
|
436
|
+
} else if (deltaY > finalDeltaY) {
|
|
437
|
+
deltaY = Math.max(finalDeltaY, 0);
|
|
438
|
+
}
|
|
439
|
+
if (state.deltaY === deltaY) {
|
|
440
|
+
return state;
|
|
441
|
+
}
|
|
442
|
+
const minLineY = Math.round(deltaY / itemHeight);
|
|
443
|
+
const maxLineY = minLineY + Math.round(listHeight / itemHeight);
|
|
444
|
+
number(minLineY);
|
|
445
|
+
number(maxLineY);
|
|
446
|
+
return {
|
|
447
|
+
...state,
|
|
448
|
+
deltaY,
|
|
449
|
+
maxLineY,
|
|
450
|
+
minLineY
|
|
451
|
+
};
|
|
452
|
+
};
|
|
453
|
+
const handleWheel = (state, deltaMode, deltaY) => {
|
|
454
|
+
object(state);
|
|
455
|
+
number(deltaMode);
|
|
456
|
+
number(deltaY);
|
|
457
|
+
return setDeltaY(state, state.deltaY + deltaY);
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const create$8 = (uid, uri, listItemHeight, x, y, width, height, platform, args, workspaceUri, assetDir) => {
|
|
461
|
+
const state = {
|
|
462
|
+
allowEmptyResult: false,
|
|
463
|
+
cursorOffset: 0,
|
|
464
|
+
height: 300,
|
|
465
|
+
icons: [],
|
|
466
|
+
maxVisibleItems: 12,
|
|
467
|
+
picks: [],
|
|
468
|
+
recentPickIds: Object.create(null),
|
|
469
|
+
recentPicks: [],
|
|
470
|
+
state: Default$1,
|
|
471
|
+
top: 50,
|
|
472
|
+
uid,
|
|
473
|
+
uri,
|
|
474
|
+
versionId: 0,
|
|
475
|
+
warned: [],
|
|
476
|
+
width: 600,
|
|
477
|
+
workspaceUri,
|
|
478
|
+
...create$9({
|
|
479
|
+
headerHeight: 38,
|
|
480
|
+
itemHeight: listItemHeight,
|
|
481
|
+
minimumSliderSize: minimumSliderSize
|
|
482
|
+
}),
|
|
483
|
+
args,
|
|
484
|
+
assetDir,
|
|
485
|
+
fileIconCache: Object.create(null),
|
|
486
|
+
focused: false,
|
|
487
|
+
inputSource: User,
|
|
488
|
+
placeholder: '',
|
|
489
|
+
platform,
|
|
490
|
+
value: ''
|
|
491
|
+
};
|
|
492
|
+
set(uid, state, state);
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const RenderItems = 1;
|
|
496
|
+
const RenderIncremental = 10;
|
|
497
|
+
const RenderFocus = 2;
|
|
498
|
+
const RenderValue = 3;
|
|
499
|
+
const RenderCursorOffset = 7;
|
|
500
|
+
const RenderFocusedIndex = 8;
|
|
501
|
+
const Height = 9;
|
|
502
|
+
|
|
503
|
+
const isEqual$4 = (oldState, newState) => {
|
|
504
|
+
return oldState.focused === newState.focused;
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
const isEqual$3 = (oldState, newState) => {
|
|
508
|
+
return oldState.focusedIndex === newState.focusedIndex;
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
const isEqual$2 = (oldState, newState) => {
|
|
512
|
+
return oldState.items.length === newState.items.length;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const isEqual$1 = (oldState, newState) => {
|
|
516
|
+
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
const diffType = RenderValue;
|
|
520
|
+
const isEqual = (oldState, newState) => {
|
|
521
|
+
return newState.inputSource === User || oldState.value === newState.value;
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
const modules = [isEqual$2, isEqual$1, isEqual, isEqual$3, isEqual$4];
|
|
525
|
+
const numbers = [Height, RenderItems, diffType, RenderFocusedIndex, RenderFocus];
|
|
526
|
+
|
|
527
|
+
const diff = (oldState, newState) => {
|
|
528
|
+
const diffResult = [];
|
|
529
|
+
for (let i = 0; i < modules.length; i++) {
|
|
530
|
+
const fn = modules[i];
|
|
531
|
+
if (!fn(oldState, newState)) {
|
|
532
|
+
diffResult.push(numbers[i]);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return diffResult;
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
const diff2 = uid => {
|
|
539
|
+
const {
|
|
540
|
+
newState,
|
|
541
|
+
oldState
|
|
542
|
+
} = get$1(uid);
|
|
543
|
+
return diff(oldState, newState);
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
const dispose = uid => {
|
|
547
|
+
dispose$1(uid);
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
const setColorTheme = id => {
|
|
551
|
+
return invoke$1(/* ColorTheme.setColorTheme */'ColorTheme.setColorTheme', /* colorThemeId */id);
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
const focusPick$1 = async pick => {
|
|
555
|
+
const {
|
|
556
|
+
label
|
|
557
|
+
} = pick;
|
|
558
|
+
await setColorTheme(label);
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
const ColorTheme$1 = 0;
|
|
562
|
+
const Commands$1 = 1;
|
|
563
|
+
const Custom$2 = 2;
|
|
564
|
+
const File$2 = 3;
|
|
565
|
+
const GoToColumn$1 = 4;
|
|
566
|
+
const GoToLine$2 = 5;
|
|
567
|
+
const Help$2 = 6;
|
|
568
|
+
const Recent$1 = 7;
|
|
569
|
+
const Symbol$3 = 8;
|
|
570
|
+
const View$3 = 9;
|
|
571
|
+
const WorkspaceSymbol$2 = 10;
|
|
572
|
+
const EveryThing$1 = 100;
|
|
573
|
+
|
|
574
|
+
const noop$1 = async () => {};
|
|
575
|
+
const getFn$2 = id => {
|
|
576
|
+
switch (id) {
|
|
577
|
+
case ColorTheme$1:
|
|
578
|
+
return focusPick$1;
|
|
579
|
+
default:
|
|
580
|
+
return noop$1;
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
const focusPick = (id, pick) => {
|
|
584
|
+
const fn = getFn$2(id);
|
|
585
|
+
return fn(pick);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
const getIconsCached = (paths, fileIconCache) => {
|
|
589
|
+
return paths.map(path => fileIconCache[path]);
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
const getMissingIconRequests = (dirents, fileIconCache) => {
|
|
593
|
+
const missingRequests = [];
|
|
594
|
+
for (const dirent of dirents) {
|
|
595
|
+
if (!dirent.path) {
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
if (!(dirent.path in fileIconCache)) {
|
|
599
|
+
missingRequests.push({
|
|
600
|
+
name: dirent.name,
|
|
601
|
+
path: dirent.path,
|
|
602
|
+
type: dirent.type
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return missingRequests;
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
const None$2 = 0;
|
|
610
|
+
const Directory = 3;
|
|
611
|
+
const File$1 = 7;
|
|
612
|
+
|
|
613
|
+
const requestFileIcon = async request => {
|
|
614
|
+
if (!request.name) {
|
|
615
|
+
return '';
|
|
616
|
+
}
|
|
617
|
+
return request.type === File$1 ? getFileIcon({
|
|
618
|
+
name: request.name
|
|
619
|
+
}) : getFolderIcon({
|
|
620
|
+
name: request.name
|
|
621
|
+
});
|
|
622
|
+
};
|
|
623
|
+
const requestFileIcons = async requests => {
|
|
624
|
+
const promises = requests.map(requestFileIcon);
|
|
625
|
+
return Promise.all(promises);
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
const updateIconCache = (iconCache, missingRequests, newIcons) => {
|
|
629
|
+
if (missingRequests.length === 0) {
|
|
630
|
+
return iconCache;
|
|
631
|
+
}
|
|
632
|
+
const newFileIconCache = {
|
|
633
|
+
...iconCache
|
|
634
|
+
};
|
|
635
|
+
for (let i = 0; i < missingRequests.length; i++) {
|
|
636
|
+
const request = missingRequests[i];
|
|
637
|
+
const icon = newIcons[i];
|
|
638
|
+
newFileIconCache[request.path] = icon;
|
|
639
|
+
}
|
|
640
|
+
return newFileIconCache;
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
const getPath = dirent => {
|
|
644
|
+
return dirent.path;
|
|
645
|
+
};
|
|
646
|
+
const toDirent = pick => {
|
|
647
|
+
const dirent = {
|
|
648
|
+
name: pick.label,
|
|
649
|
+
path: pick.uri,
|
|
650
|
+
type: pick.direntType
|
|
651
|
+
};
|
|
652
|
+
return dirent;
|
|
653
|
+
};
|
|
654
|
+
const getQuickPickFileIcons = async (items, fileIconCache) => {
|
|
655
|
+
const dirents = items.map(toDirent);
|
|
656
|
+
const missingRequests = getMissingIconRequests(dirents, fileIconCache);
|
|
657
|
+
const newIcons = await requestFileIcons(missingRequests);
|
|
658
|
+
const newFileIconCache = updateIconCache(fileIconCache, missingRequests, newIcons);
|
|
659
|
+
const paths = dirents.map(getPath);
|
|
660
|
+
const icons = getIconsCached(paths, newFileIconCache);
|
|
661
|
+
return {
|
|
662
|
+
icons,
|
|
663
|
+
newFileIconCache
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
const focusIndex = async (state, index) => {
|
|
668
|
+
const {
|
|
669
|
+
fileIconCache,
|
|
670
|
+
items,
|
|
671
|
+
maxLineY,
|
|
672
|
+
maxVisibleItems,
|
|
673
|
+
minLineY,
|
|
674
|
+
providerId
|
|
675
|
+
} = state;
|
|
676
|
+
await focusPick(providerId, items[index]);
|
|
677
|
+
if (index < minLineY + 1) {
|
|
678
|
+
const minLineY = index;
|
|
679
|
+
const maxLineY = Math.min(index + maxVisibleItems, items.length - 1);
|
|
680
|
+
const sliced = items.slice(minLineY, maxLineY);
|
|
681
|
+
const {
|
|
682
|
+
icons,
|
|
683
|
+
newFileIconCache
|
|
684
|
+
} = await getQuickPickFileIcons(sliced, fileIconCache);
|
|
685
|
+
|
|
686
|
+
// TODO need to scroll up
|
|
687
|
+
return {
|
|
688
|
+
...state,
|
|
689
|
+
fileIconCache: newFileIconCache,
|
|
690
|
+
focusedIndex: index,
|
|
691
|
+
icons,
|
|
692
|
+
maxLineY,
|
|
693
|
+
minLineY
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
if (index >= maxLineY - 1) {
|
|
697
|
+
// TODO need to scroll down
|
|
698
|
+
const maxLineY = index + 1;
|
|
699
|
+
const minLineY = Math.max(maxLineY - maxVisibleItems, 0);
|
|
700
|
+
const sliced = items.slice(minLineY, maxLineY);
|
|
701
|
+
const {
|
|
702
|
+
icons,
|
|
703
|
+
newFileIconCache
|
|
704
|
+
} = await getQuickPickFileIcons(sliced, fileIconCache);
|
|
705
|
+
return {
|
|
706
|
+
...state,
|
|
707
|
+
fileIconCache: newFileIconCache,
|
|
708
|
+
focusedIndex: index,
|
|
709
|
+
icons,
|
|
710
|
+
maxLineY,
|
|
711
|
+
minLineY
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
const sliced = items.slice(minLineY, maxLineY);
|
|
715
|
+
const {
|
|
716
|
+
icons,
|
|
717
|
+
newFileIconCache
|
|
718
|
+
} = await getQuickPickFileIcons(sliced, fileIconCache);
|
|
719
|
+
return {
|
|
720
|
+
...state,
|
|
721
|
+
fileIconCache: newFileIconCache,
|
|
722
|
+
focusedIndex: index,
|
|
723
|
+
icons
|
|
724
|
+
};
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
const first = () => {
|
|
728
|
+
return 0;
|
|
729
|
+
};
|
|
730
|
+
const last = items => {
|
|
731
|
+
return items.length - 1;
|
|
732
|
+
};
|
|
733
|
+
const next = (items, index) => {
|
|
734
|
+
return (index + 1) % items.length;
|
|
735
|
+
};
|
|
736
|
+
const previous = (items, index) => {
|
|
737
|
+
return index === 0 ? items.length - 1 : index - 1;
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
const focusFirst = state => {
|
|
741
|
+
return focusIndex(state, first());
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
const focusLast = state => {
|
|
745
|
+
const {
|
|
746
|
+
items
|
|
747
|
+
} = state;
|
|
748
|
+
return focusIndex(state, last(items));
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
const focusNext = state => {
|
|
752
|
+
const {
|
|
753
|
+
focusedIndex,
|
|
754
|
+
items
|
|
755
|
+
} = state;
|
|
756
|
+
const nextIndex = next(items, focusedIndex);
|
|
757
|
+
return focusIndex(state, nextIndex);
|
|
758
|
+
};
|
|
759
|
+
|
|
760
|
+
const focusPrevious = state => {
|
|
761
|
+
const {
|
|
762
|
+
focusedIndex,
|
|
763
|
+
items
|
|
764
|
+
} = state;
|
|
765
|
+
const previousIndex = previous(items, focusedIndex);
|
|
766
|
+
return focusIndex(state, previousIndex);
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
const SetDom2 = 'Viewlet.setDom2';
|
|
770
|
+
const SetPatches = 'Viewlet.setPatches';
|
|
771
|
+
|
|
772
|
+
const FocusQuickPickInput = 20;
|
|
773
|
+
|
|
774
|
+
const Enter = 3;
|
|
775
|
+
const Escape = 8;
|
|
776
|
+
const PageUp = 10;
|
|
777
|
+
const PageDown = 11;
|
|
778
|
+
const UpArrow = 14;
|
|
779
|
+
const DownArrow = 16;
|
|
780
|
+
|
|
781
|
+
const getKeyBindings = () => {
|
|
782
|
+
return [{
|
|
783
|
+
args: ['QuickPick'],
|
|
784
|
+
command: 'Viewlet.closeWidget',
|
|
785
|
+
key: Escape,
|
|
786
|
+
when: FocusQuickPickInput
|
|
787
|
+
}, {
|
|
788
|
+
command: 'QuickPick.focusPrevious',
|
|
789
|
+
key: UpArrow,
|
|
790
|
+
when: FocusQuickPickInput
|
|
791
|
+
}, {
|
|
792
|
+
command: 'QuickPick.focusNext',
|
|
793
|
+
key: DownArrow,
|
|
794
|
+
when: FocusQuickPickInput
|
|
795
|
+
}, {
|
|
796
|
+
command: 'QuickPick.focusFirst',
|
|
797
|
+
key: PageUp,
|
|
798
|
+
when: FocusQuickPickInput
|
|
799
|
+
}, {
|
|
800
|
+
command: 'QuickPick.focusLast',
|
|
801
|
+
key: PageDown,
|
|
802
|
+
when: FocusQuickPickInput
|
|
803
|
+
}, {
|
|
804
|
+
command: 'QuickPick.selectCurrentIndex',
|
|
805
|
+
key: Enter,
|
|
806
|
+
when: FocusQuickPickInput
|
|
807
|
+
}];
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
const getNewValueDeleteContentBackward = (value, selectionStart, selectionEnd, data) => {
|
|
811
|
+
const after = value.slice(selectionEnd);
|
|
812
|
+
if (selectionStart === selectionEnd) {
|
|
813
|
+
const before = value.slice(0, selectionStart - 1);
|
|
814
|
+
const newValue = before + after;
|
|
815
|
+
return {
|
|
816
|
+
cursorOffset: before.length,
|
|
817
|
+
newValue
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
const before = value.slice(0, selectionStart);
|
|
821
|
+
const newValue = before + after;
|
|
822
|
+
return {
|
|
823
|
+
cursorOffset: selectionStart,
|
|
824
|
+
newValue
|
|
825
|
+
};
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
const getNewValueDeleteContentForward = (value, selectionStart, selectionEnd, data) => {
|
|
829
|
+
const before = value.slice(0, selectionStart);
|
|
830
|
+
if (selectionStart === selectionEnd) {
|
|
831
|
+
const after = value.slice(selectionEnd + 1);
|
|
832
|
+
const newValue = before + after;
|
|
833
|
+
return {
|
|
834
|
+
cursorOffset: selectionStart,
|
|
835
|
+
newValue
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
const after = value.slice(selectionEnd);
|
|
839
|
+
const newValue = before + after;
|
|
840
|
+
return {
|
|
841
|
+
cursorOffset: selectionStart,
|
|
842
|
+
newValue
|
|
843
|
+
};
|
|
844
|
+
};
|
|
845
|
+
|
|
846
|
+
const RE_ALPHA_NUMERIC = /[a-z\d]/i;
|
|
847
|
+
const isAlphaNumeric = character => {
|
|
848
|
+
return RE_ALPHA_NUMERIC.test(character);
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
const getNewValueDeleteWordBackward = (value, selectionStart, selectionEnd, data) => {
|
|
852
|
+
const after = value.slice(selectionEnd);
|
|
853
|
+
if (selectionStart === selectionEnd) {
|
|
854
|
+
let startIndex = Math.max(selectionStart - 1, 0);
|
|
855
|
+
while (startIndex > 0 && isAlphaNumeric(value[startIndex])) {
|
|
856
|
+
startIndex--;
|
|
857
|
+
}
|
|
858
|
+
const before = value.slice(0, startIndex);
|
|
859
|
+
const newValue = before + after;
|
|
860
|
+
return {
|
|
861
|
+
cursorOffset: before.length,
|
|
862
|
+
newValue
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
const before = value.slice(0, selectionStart);
|
|
866
|
+
const newValue = before + after;
|
|
867
|
+
return {
|
|
868
|
+
cursorOffset: selectionStart,
|
|
869
|
+
newValue
|
|
870
|
+
};
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
const getNewValueDeleteWordForward = (value, selectionStart, selectionEnd, data) => {
|
|
874
|
+
const before = value.slice(0, selectionStart);
|
|
875
|
+
if (selectionStart === selectionEnd) {
|
|
876
|
+
let startIndex = Math.min(selectionStart + 1, value.length - 1);
|
|
877
|
+
while (startIndex < value.length && isAlphaNumeric(value[startIndex])) {
|
|
878
|
+
startIndex++;
|
|
879
|
+
}
|
|
880
|
+
const after = value.slice(startIndex);
|
|
881
|
+
const newValue = before + after;
|
|
882
|
+
return {
|
|
883
|
+
cursorOffset: before.length,
|
|
884
|
+
newValue
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
const after = value.slice(selectionEnd);
|
|
888
|
+
const newValue = before + after;
|
|
889
|
+
return {
|
|
890
|
+
cursorOffset: selectionStart,
|
|
891
|
+
newValue
|
|
892
|
+
};
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
const getNewValueInsertText = (value, selectionStart, selectionEnd, data) => {
|
|
896
|
+
if (selectionStart === value.length) {
|
|
897
|
+
const newValue = value + data;
|
|
898
|
+
return {
|
|
899
|
+
cursorOffset: newValue.length,
|
|
900
|
+
newValue
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
const before = value.slice(0, selectionStart);
|
|
904
|
+
const after = value.slice(selectionEnd);
|
|
905
|
+
const newValue = before + data + after;
|
|
906
|
+
return {
|
|
907
|
+
cursorOffset: selectionStart + data.length,
|
|
908
|
+
newValue
|
|
909
|
+
};
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
const getNewValueInsertCompositionText = (value, selectionStart, selectionEnd, data) => {
|
|
913
|
+
return getNewValueInsertText(value, selectionStart, selectionEnd, data);
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
const getNewValueInsertLineBreak = (value, selectionStart, selectionEnd, data) => {
|
|
917
|
+
return {
|
|
918
|
+
cursorOffset: selectionEnd,
|
|
919
|
+
newValue: value
|
|
920
|
+
};
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
const InsertText = 'insertText';
|
|
924
|
+
const DeleteContentBackward = 'deleteContentBackward';
|
|
925
|
+
const DeleteContentForward = 'deleteContentForward';
|
|
926
|
+
const DeleteWordForward = 'deleteWordForward';
|
|
927
|
+
const DeleteWordBackward = 'deleteWordBackward';
|
|
928
|
+
const InsertLineBreak = 'insertLineBreak';
|
|
929
|
+
const InsertCompositionText = 'insertCompositionText';
|
|
930
|
+
const InsertFromPaste = 'insertFromPaste';
|
|
931
|
+
|
|
932
|
+
const getNewValueFunction = inputType => {
|
|
933
|
+
switch (inputType) {
|
|
934
|
+
case DeleteContentBackward:
|
|
935
|
+
return getNewValueDeleteContentBackward;
|
|
936
|
+
case DeleteContentForward:
|
|
937
|
+
return getNewValueDeleteContentForward;
|
|
938
|
+
case DeleteWordBackward:
|
|
939
|
+
return getNewValueDeleteWordBackward;
|
|
940
|
+
case DeleteWordForward:
|
|
941
|
+
return getNewValueDeleteWordForward;
|
|
942
|
+
case InsertCompositionText:
|
|
943
|
+
return getNewValueInsertCompositionText;
|
|
944
|
+
case InsertFromPaste:
|
|
945
|
+
case InsertText:
|
|
946
|
+
return getNewValueInsertText;
|
|
947
|
+
case InsertLineBreak:
|
|
948
|
+
return getNewValueInsertLineBreak;
|
|
949
|
+
default:
|
|
950
|
+
throw new Error(`unsupported input type ${inputType}`);
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
|
|
954
|
+
const getNewValue = (value, inputType, data, selectionStart, selectionEnd) => {
|
|
955
|
+
const fn = getNewValueFunction(inputType);
|
|
956
|
+
return fn(value, selectionStart, selectionEnd, data);
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
const Diagonal = 1;
|
|
960
|
+
const Left = 2;
|
|
961
|
+
|
|
962
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
963
|
+
|
|
964
|
+
const createTable = size => {
|
|
965
|
+
const table = [];
|
|
966
|
+
for (let i = 0; i < size; i++) {
|
|
967
|
+
const row = new Uint8Array(size);
|
|
968
|
+
table.push(row);
|
|
969
|
+
}
|
|
970
|
+
return table;
|
|
971
|
+
};
|
|
972
|
+
const EmptyMatches = [];
|
|
973
|
+
const Dash = '-';
|
|
974
|
+
const Dot = '.';
|
|
975
|
+
const EmptyString = '';
|
|
976
|
+
const Space = ' ';
|
|
977
|
+
const Underline = '_';
|
|
978
|
+
const T = 't';
|
|
979
|
+
const isLowerCase = char => {
|
|
980
|
+
return char === char.toLowerCase();
|
|
981
|
+
};
|
|
982
|
+
const isUpperCase = char => {
|
|
983
|
+
return char === char.toUpperCase();
|
|
984
|
+
};
|
|
985
|
+
|
|
986
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
987
|
+
const isGap = (columnCharBefore, columnChar) => {
|
|
988
|
+
switch (columnCharBefore) {
|
|
989
|
+
case Dash:
|
|
990
|
+
case Underline:
|
|
991
|
+
case EmptyString:
|
|
992
|
+
case T:
|
|
993
|
+
case Space:
|
|
994
|
+
case Dot:
|
|
995
|
+
return true;
|
|
996
|
+
}
|
|
997
|
+
if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
|
|
998
|
+
return true;
|
|
999
|
+
}
|
|
1000
|
+
return false;
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
1004
|
+
const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch) => {
|
|
1005
|
+
if (rowCharLow !== columnCharLow) {
|
|
1006
|
+
return -1;
|
|
1007
|
+
}
|
|
1008
|
+
const isMatch = rowChar === columnChar;
|
|
1009
|
+
if (isMatch) {
|
|
1010
|
+
if (isDiagonalMatch) {
|
|
1011
|
+
return 8;
|
|
1012
|
+
}
|
|
1013
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
1014
|
+
return 8;
|
|
1015
|
+
}
|
|
1016
|
+
return 5;
|
|
1017
|
+
}
|
|
1018
|
+
if (isGap(columnCharBefore, columnChar)) {
|
|
1019
|
+
return 8;
|
|
1020
|
+
}
|
|
1021
|
+
return 5;
|
|
1022
|
+
};
|
|
1023
|
+
|
|
1024
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
1025
|
+
|
|
1026
|
+
const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
|
|
1027
|
+
while (patternPos < patternLen && wordPos < wordLen) {
|
|
1028
|
+
if (patternLow[patternPos] === wordLow[wordPos]) {
|
|
1029
|
+
patternPos += 1;
|
|
1030
|
+
}
|
|
1031
|
+
wordPos += 1;
|
|
1032
|
+
}
|
|
1033
|
+
return patternPos === patternLen; // pattern must be exhausted
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
1037
|
+
const traceHighlights = (table, arrows, patternLength, wordLength) => {
|
|
1038
|
+
let row = patternLength;
|
|
1039
|
+
let column = wordLength;
|
|
1040
|
+
const matches = [];
|
|
1041
|
+
while (row >= 1 && column >= 1) {
|
|
1042
|
+
const arrow = arrows[row][column];
|
|
1043
|
+
if (arrow === Left) {
|
|
1044
|
+
column--;
|
|
1045
|
+
} else if (arrow === Diagonal) {
|
|
1046
|
+
row--;
|
|
1047
|
+
column--;
|
|
1048
|
+
const start = column + 1;
|
|
1049
|
+
while (row >= 1 && column >= 1) {
|
|
1050
|
+
const arrow = arrows[row][column];
|
|
1051
|
+
if (arrow === Left) {
|
|
1052
|
+
break;
|
|
1053
|
+
}
|
|
1054
|
+
if (arrow === Diagonal) {
|
|
1055
|
+
row--;
|
|
1056
|
+
column--;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
const end = column;
|
|
1060
|
+
matches.unshift(end, start);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
matches.unshift(table[patternLength][wordLength - 1]);
|
|
1064
|
+
return matches;
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
// based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
|
|
1068
|
+
const gridSize = 128;
|
|
1069
|
+
const table = createTable(gridSize);
|
|
1070
|
+
const arrows = createTable(gridSize);
|
|
1071
|
+
const fuzzySearch = (pattern, word) => {
|
|
1072
|
+
const patternLength = Math.min(pattern.length, gridSize - 1);
|
|
1073
|
+
const wordLength = Math.min(word.length, gridSize - 1);
|
|
1074
|
+
const patternLower = pattern.toLowerCase();
|
|
1075
|
+
const wordLower = word.toLowerCase();
|
|
1076
|
+
if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
|
|
1077
|
+
return EmptyMatches;
|
|
1078
|
+
}
|
|
1079
|
+
let strongMatch = false;
|
|
1080
|
+
for (let row = 1; row < patternLength + 1; row++) {
|
|
1081
|
+
const rowChar = pattern[row - 1];
|
|
1082
|
+
const rowCharLow = patternLower[row - 1];
|
|
1083
|
+
for (let column = 1; column < wordLength + 1; column++) {
|
|
1084
|
+
const columnChar = word[column - 1];
|
|
1085
|
+
const columnCharLow = wordLower[column - 1];
|
|
1086
|
+
const columnCharBefore = word[column - 2] || '';
|
|
1087
|
+
const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
|
|
1088
|
+
const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, isDiagonalMatch);
|
|
1089
|
+
if (row === 1 && score > 5) {
|
|
1090
|
+
strongMatch = true;
|
|
1091
|
+
}
|
|
1092
|
+
let diagonalScore = score + table[row - 1][column - 1];
|
|
1093
|
+
if (isDiagonalMatch && score !== -1) {
|
|
1094
|
+
diagonalScore += 2;
|
|
1095
|
+
}
|
|
1096
|
+
const leftScore = table[row][column - 1];
|
|
1097
|
+
if (leftScore > diagonalScore) {
|
|
1098
|
+
table[row][column] = leftScore;
|
|
1099
|
+
arrows[row][column] = Left;
|
|
1100
|
+
} else {
|
|
1101
|
+
table[row][column] = diagonalScore;
|
|
1102
|
+
arrows[row][column] = Diagonal;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
if (!strongMatch) {
|
|
1107
|
+
return EmptyMatches;
|
|
1108
|
+
}
|
|
1109
|
+
const highlights = traceHighlights(table, arrows, patternLength, wordLength);
|
|
1110
|
+
return highlights;
|
|
1111
|
+
};
|
|
1112
|
+
|
|
1113
|
+
const filterQuickPickItem = (pattern, word) => {
|
|
1114
|
+
const matches = fuzzySearch(pattern, word);
|
|
1115
|
+
return matches;
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
const filterQuickPickItems = (items, value) => {
|
|
1119
|
+
if (!value) {
|
|
1120
|
+
return items;
|
|
1121
|
+
}
|
|
1122
|
+
const results = [];
|
|
1123
|
+
for (const item of items) {
|
|
1124
|
+
const filterValue = item.label;
|
|
1125
|
+
const matches = filterQuickPickItem(value, filterValue);
|
|
1126
|
+
if (matches.length > 0) {
|
|
1127
|
+
results.push({
|
|
1128
|
+
...item,
|
|
1129
|
+
matches
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return results;
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
const Command = '>';
|
|
1137
|
+
const Symbol$2 = '@';
|
|
1138
|
+
const WorkspaceSymbol$1 = '#';
|
|
1139
|
+
const GoToLine$1 = ':';
|
|
1140
|
+
const View$2 = 'view ';
|
|
1141
|
+
const None$1 = '';
|
|
1142
|
+
const Help$1 = '?';
|
|
1143
|
+
const GoToColumn = '::';
|
|
1144
|
+
|
|
1145
|
+
const getQuickPickPrefix = value => {
|
|
1146
|
+
if (value.startsWith(Command)) {
|
|
1147
|
+
return Command;
|
|
1148
|
+
}
|
|
1149
|
+
if (value.startsWith(Symbol$2)) {
|
|
1150
|
+
return Symbol$2;
|
|
1151
|
+
}
|
|
1152
|
+
if (value.startsWith(WorkspaceSymbol$1)) {
|
|
1153
|
+
return WorkspaceSymbol$1;
|
|
1154
|
+
}
|
|
1155
|
+
if (value.startsWith(GoToColumn)) {
|
|
1156
|
+
return GoToColumn;
|
|
1157
|
+
}
|
|
1158
|
+
if (value.startsWith(GoToLine$1)) {
|
|
1159
|
+
return GoToLine$1;
|
|
1160
|
+
}
|
|
1161
|
+
if (value.startsWith(View$2)) {
|
|
1162
|
+
return View$2;
|
|
1163
|
+
}
|
|
1164
|
+
return None$1;
|
|
1165
|
+
};
|
|
1166
|
+
|
|
1167
|
+
const noop = value => {
|
|
1168
|
+
return value;
|
|
1169
|
+
};
|
|
1170
|
+
const getFilterValueEverything = value => {
|
|
1171
|
+
const prefix = getQuickPickPrefix(value);
|
|
1172
|
+
const prefixLength = prefix.length;
|
|
1173
|
+
return value.slice(prefixLength).trim();
|
|
1174
|
+
};
|
|
1175
|
+
const getValueGoToColumn = value => {
|
|
1176
|
+
return '';
|
|
1177
|
+
};
|
|
1178
|
+
const getValueGoToLine = value => {
|
|
1179
|
+
return '';
|
|
1180
|
+
};
|
|
1181
|
+
const getFn$1 = id => {
|
|
1182
|
+
switch (id) {
|
|
1183
|
+
case EveryThing$1:
|
|
1184
|
+
return getFilterValueEverything;
|
|
1185
|
+
case GoToColumn$1:
|
|
1186
|
+
return getValueGoToColumn;
|
|
1187
|
+
case GoToLine$2:
|
|
1188
|
+
return getValueGoToLine;
|
|
1189
|
+
default:
|
|
1190
|
+
return noop;
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
const getFilterValue = (id, subId, value) => {
|
|
1194
|
+
if (subId === GoToColumn$1) {
|
|
1195
|
+
return getValueGoToColumn();
|
|
1196
|
+
}
|
|
1197
|
+
if (subId === GoToLine$2) {
|
|
1198
|
+
return getValueGoToLine();
|
|
1199
|
+
}
|
|
1200
|
+
const fn = getFn$1(id);
|
|
1201
|
+
const filterValue = fn(value);
|
|
1202
|
+
return filterValue;
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
const getFinalDeltaY = (height, itemHeight, itemsLength) => {
|
|
1206
|
+
const contentHeight = itemsLength * itemHeight;
|
|
1207
|
+
const finalDeltaY = Math.max(contentHeight - height, 0);
|
|
1208
|
+
return finalDeltaY;
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
const getListHeight = (itemsLength, itemHeight, maxHeight) => {
|
|
1212
|
+
number(itemsLength);
|
|
1213
|
+
number(itemHeight);
|
|
1214
|
+
number(maxHeight);
|
|
1215
|
+
if (itemsLength === 0) {
|
|
1216
|
+
return itemHeight;
|
|
1217
|
+
}
|
|
1218
|
+
const totalHeight = itemsLength * itemHeight;
|
|
1219
|
+
return Math.min(totalHeight, maxHeight);
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
const getColorThemeNames = async (assetDir, platform) => {
|
|
1223
|
+
return invoke$1('ColorTheme.getColorThemeNames', assetDir, platform);
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
const toProtoVisibleItem$3 = name => {
|
|
1227
|
+
const pick = {
|
|
1228
|
+
description: '',
|
|
1229
|
+
direntType: 0,
|
|
1230
|
+
fileIcon: '',
|
|
1231
|
+
icon: '',
|
|
1232
|
+
label: name,
|
|
1233
|
+
matches: [],
|
|
1234
|
+
uri: ''
|
|
1235
|
+
};
|
|
1236
|
+
return pick;
|
|
1237
|
+
};
|
|
1238
|
+
const getPicks$c = async (searchValue, args, {
|
|
1239
|
+
assetDir = '',
|
|
1240
|
+
platform = 0
|
|
1241
|
+
} = {}) => {
|
|
1242
|
+
const colorThemeNames = await getColorThemeNames(assetDir, platform);
|
|
1243
|
+
const picks = colorThemeNames.map(toProtoVisibleItem$3);
|
|
1244
|
+
return picks;
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
const handleError = async (error, notify = true, prefix = '') => {
|
|
1248
|
+
console.error(error);
|
|
1249
|
+
};
|
|
1250
|
+
const showErrorDialog = async error => {
|
|
1251
|
+
const {
|
|
1252
|
+
code
|
|
1253
|
+
} = error;
|
|
1254
|
+
const {
|
|
1255
|
+
message
|
|
1256
|
+
} = error;
|
|
1257
|
+
const {
|
|
1258
|
+
stack
|
|
1259
|
+
} = error;
|
|
1260
|
+
const {
|
|
1261
|
+
name
|
|
1262
|
+
} = error;
|
|
1263
|
+
const errorInfo = {
|
|
1264
|
+
code,
|
|
1265
|
+
message,
|
|
1266
|
+
name,
|
|
1267
|
+
stack
|
|
1268
|
+
};
|
|
1269
|
+
await showErrorDialog$1(errorInfo);
|
|
1270
|
+
};
|
|
1271
|
+
const warn$1 = (...args) => {
|
|
1272
|
+
console.warn(...args);
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
const state$2 = {
|
|
1276
|
+
menuEntries: []
|
|
1277
|
+
};
|
|
1278
|
+
const getAll = async () => {
|
|
1279
|
+
try {
|
|
1280
|
+
// @ts-ignore
|
|
1281
|
+
const entries = await invoke$1('Layout.getAllQuickPickMenuEntries');
|
|
1282
|
+
return entries || [];
|
|
1283
|
+
} catch {
|
|
1284
|
+
// ignore
|
|
1285
|
+
}
|
|
1286
|
+
return state$2.menuEntries;
|
|
1287
|
+
};
|
|
1288
|
+
const add = menuEntries => {
|
|
1289
|
+
state$2.menuEntries = [...state$2.menuEntries, ...menuEntries];
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1292
|
+
// TODO combine Ajax with cache (specify strategy: cacheFirst, networkFirst)
|
|
1293
|
+
const getBuiltinPicks = async () => {
|
|
1294
|
+
const builtinPicks = await getAll();
|
|
1295
|
+
return builtinPicks;
|
|
1296
|
+
};
|
|
1297
|
+
const prefixIdWithExt = item => {
|
|
1298
|
+
if (!item.label) {
|
|
1299
|
+
warn$1('[QuickPick] item has missing label', item);
|
|
1300
|
+
}
|
|
1301
|
+
if (!item.id) {
|
|
1302
|
+
warn$1('[QuickPick] item has missing id', item);
|
|
1303
|
+
}
|
|
1304
|
+
return {
|
|
1305
|
+
...item,
|
|
1306
|
+
id: `ext.${item.id}`,
|
|
1307
|
+
label: item.label || item.id
|
|
1308
|
+
};
|
|
1309
|
+
};
|
|
1310
|
+
const getExtensionPicks = async (assetDir, platform) => {
|
|
1311
|
+
try {
|
|
1312
|
+
// TODO
|
|
1313
|
+
// Assert.string(assetDir)
|
|
1314
|
+
// Assert.number(platform)
|
|
1315
|
+
// TODO ask extension management worker directly
|
|
1316
|
+
// TODO don't call this every time, cache the results
|
|
1317
|
+
const extensionPicks = await invoke$1('ExtensionHost.getCommands', assetDir, platform);
|
|
1318
|
+
if (!extensionPicks) {
|
|
1319
|
+
return [];
|
|
1320
|
+
}
|
|
1321
|
+
const mappedPicks = extensionPicks.map(prefixIdWithExt);
|
|
1322
|
+
return mappedPicks;
|
|
1323
|
+
} catch (error) {
|
|
1324
|
+
console.error(`Failed to get extension picks: ${error}`);
|
|
1325
|
+
return [];
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
const toProtoVisibleItem$2 = item => {
|
|
1329
|
+
const pick = {
|
|
1330
|
+
// @ts-ignore
|
|
1331
|
+
args: item.args,
|
|
1332
|
+
description: '',
|
|
1333
|
+
direntType: 0,
|
|
1334
|
+
fileIcon: '',
|
|
1335
|
+
icon: '',
|
|
1336
|
+
// @ts-ignore
|
|
1337
|
+
id: item.id,
|
|
1338
|
+
label: item.label,
|
|
1339
|
+
matches: [],
|
|
1340
|
+
uri: ''
|
|
1341
|
+
};
|
|
1342
|
+
// @ts-ignore
|
|
1343
|
+
return pick;
|
|
1344
|
+
};
|
|
1345
|
+
const getPicks$b = async (value, args, {
|
|
1346
|
+
assetDir = '',
|
|
1347
|
+
platform = 0
|
|
1348
|
+
} = {}) => {
|
|
1349
|
+
// TODO get picks in parallel
|
|
1350
|
+
const builtinPicks = await getBuiltinPicks();
|
|
1351
|
+
const extensionPicks = await getExtensionPicks(assetDir, platform);
|
|
1352
|
+
const allPicks = [...builtinPicks, ...extensionPicks];
|
|
1353
|
+
const converted = allPicks.map(toProtoVisibleItem$2);
|
|
1354
|
+
return converted;
|
|
1355
|
+
};
|
|
1356
|
+
|
|
1357
|
+
const toProtoVisibleItem$1 = item => {
|
|
1358
|
+
const {
|
|
1359
|
+
label
|
|
1360
|
+
} = item;
|
|
1361
|
+
return {
|
|
1362
|
+
description: '',
|
|
1363
|
+
direntType: 0,
|
|
1364
|
+
fileIcon: '',
|
|
1365
|
+
icon: '',
|
|
1366
|
+
label,
|
|
1367
|
+
matches: [],
|
|
1368
|
+
uri: ''
|
|
1369
|
+
};
|
|
1370
|
+
};
|
|
1371
|
+
const getPicks$a = async (searchValue, args) => {
|
|
1372
|
+
const items = args[1] || [];
|
|
1373
|
+
const mapped = items.map(toProtoVisibleItem$1);
|
|
1374
|
+
return mapped;
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1377
|
+
const emptyMatches = [];
|
|
1378
|
+
|
|
1379
|
+
const getWorkspacePath = async () => {
|
|
1380
|
+
return invoke$1('Workspace.getPath');
|
|
1381
|
+
};
|
|
1382
|
+
|
|
1383
|
+
const RE_PROTOCOL = /^([a-z-]+):\/\//;
|
|
1384
|
+
const getProtocol = uri => {
|
|
1385
|
+
const protocolMatch = uri.match(RE_PROTOCOL);
|
|
1386
|
+
if (protocolMatch) {
|
|
1387
|
+
return protocolMatch[1];
|
|
1388
|
+
}
|
|
1389
|
+
return '';
|
|
1390
|
+
};
|
|
1391
|
+
|
|
1392
|
+
const state$1 = Object.create(null);
|
|
1393
|
+
const register = modules => {
|
|
1394
|
+
Object.assign(state$1, modules);
|
|
1395
|
+
};
|
|
1396
|
+
const getFn = protocol => {
|
|
1397
|
+
return state$1[protocol];
|
|
1398
|
+
};
|
|
1399
|
+
|
|
1400
|
+
const searchFile$5 = async (path, value, prepare, assetDir) => {
|
|
1401
|
+
const protocol = getProtocol(path);
|
|
1402
|
+
// TODO call different providers depending on protocol
|
|
1403
|
+
const fn = getFn(protocol);
|
|
1404
|
+
if (!fn) {
|
|
1405
|
+
throw new Error(`No search handler registered for protocol: ${protocol}`);
|
|
1406
|
+
}
|
|
1407
|
+
const result = await fn(path, value, prepare, assetDir);
|
|
1408
|
+
return result;
|
|
1409
|
+
};
|
|
1410
|
+
|
|
1411
|
+
// TODO this should be in FileSystem module
|
|
1412
|
+
const pathBaseName = path => {
|
|
1413
|
+
return path.slice(path.lastIndexOf('/') + 1);
|
|
1414
|
+
};
|
|
1415
|
+
|
|
1416
|
+
// TODO this should be in FileSystem module
|
|
1417
|
+
const pathDirName = path => {
|
|
1418
|
+
const pathSeparator = '/';
|
|
1419
|
+
const index = path.lastIndexOf(pathSeparator);
|
|
1420
|
+
if (index === -1) {
|
|
1421
|
+
return '';
|
|
1422
|
+
}
|
|
1423
|
+
return path.slice(0, index);
|
|
1424
|
+
};
|
|
1425
|
+
|
|
1426
|
+
const searchFile$4 = async (path, value) => {
|
|
1427
|
+
const prepare = true;
|
|
1428
|
+
const files = await searchFile$5(/* path */path, /* searchTerm */value, prepare, '');
|
|
1429
|
+
return files;
|
|
1430
|
+
};
|
|
1431
|
+
const convertToPick = uri => {
|
|
1432
|
+
const baseName = pathBaseName(uri);
|
|
1433
|
+
const dirName = pathDirName(uri);
|
|
1434
|
+
return {
|
|
1435
|
+
description: dirName,
|
|
1436
|
+
direntType: File$1,
|
|
1437
|
+
fileIcon: '',
|
|
1438
|
+
icon: '',
|
|
1439
|
+
label: baseName,
|
|
1440
|
+
matches: emptyMatches,
|
|
1441
|
+
uri
|
|
1442
|
+
};
|
|
1443
|
+
};
|
|
1444
|
+
|
|
1445
|
+
// TODO handle files differently
|
|
1446
|
+
// e.g. when there are many files, don't need
|
|
1447
|
+
// to compute the fileIcon for all files
|
|
1448
|
+
|
|
1449
|
+
const getPicks$9 = async searchValue => {
|
|
1450
|
+
// TODO cache workspace path
|
|
1451
|
+
const workspace = await getWorkspacePath();
|
|
1452
|
+
if (!workspace) {
|
|
1453
|
+
return [];
|
|
1454
|
+
}
|
|
1455
|
+
const files = await searchFile$4(workspace, searchValue);
|
|
1456
|
+
const picks = files.map(convertToPick);
|
|
1457
|
+
return picks;
|
|
1458
|
+
};
|
|
1459
|
+
|
|
1460
|
+
const getText = async () => {
|
|
1461
|
+
// TODO
|
|
1462
|
+
const id = await getActiveEditorId();
|
|
1463
|
+
const lines = await getLines(id);
|
|
1464
|
+
return lines.join('\n');
|
|
1465
|
+
};
|
|
1466
|
+
|
|
1467
|
+
const getPicksGoToColumnBase = async () => {
|
|
1468
|
+
const text = await getText();
|
|
1469
|
+
return [{
|
|
1470
|
+
description: '',
|
|
1471
|
+
direntType: 0,
|
|
1472
|
+
fileIcon: '',
|
|
1473
|
+
icon: '',
|
|
1474
|
+
label: `Type a character position to go to (from 1 to ${text.length})`,
|
|
1475
|
+
matches: [],
|
|
1476
|
+
uri: ''
|
|
1477
|
+
}];
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
const getPosition = (text, wantedColumn) => {
|
|
1481
|
+
let row = 0;
|
|
1482
|
+
let column = 0;
|
|
1483
|
+
for (let i = 0; i < wantedColumn; i++) {
|
|
1484
|
+
if (text[i] === '\n') {
|
|
1485
|
+
row++;
|
|
1486
|
+
column = 0;
|
|
1487
|
+
} else {
|
|
1488
|
+
column++;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
return {
|
|
1492
|
+
column,
|
|
1493
|
+
row
|
|
1494
|
+
};
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1497
|
+
const emptyObject = {};
|
|
1498
|
+
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
1499
|
+
const i18nString = (key, placeholders = emptyObject) => {
|
|
1500
|
+
if (placeholders === emptyObject) {
|
|
1501
|
+
return key;
|
|
1502
|
+
}
|
|
1503
|
+
const replacer = (match, rest) => {
|
|
1504
|
+
return placeholders[rest];
|
|
1505
|
+
};
|
|
1506
|
+
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
1507
|
+
};
|
|
1508
|
+
|
|
1509
|
+
const GoToFile = 'Go to file';
|
|
1510
|
+
const GoToLineColumn = 'Go to Line / Column';
|
|
1511
|
+
const GoToSymbolInEditor = 'Go to Symbol in Editor';
|
|
1512
|
+
const NoResults = 'No Results';
|
|
1513
|
+
const OpenView = 'Open View';
|
|
1514
|
+
const QuickOpen = 'Quick open';
|
|
1515
|
+
const SearchForText = 'Search for text';
|
|
1516
|
+
const ShowAndRunCommands = 'Show And Run Commands';
|
|
1517
|
+
const TypeNameOfCommandToRun = 'Type the name of a command to run.';
|
|
1518
|
+
const PressEnterToGoToLine = `Press 'Enter' to go to line {PH1} column {PH2}`;
|
|
1519
|
+
|
|
1520
|
+
const pressEnterToGoToLine = (row, column) => {
|
|
1521
|
+
return i18nString(PressEnterToGoToLine, {
|
|
1522
|
+
PH1: row,
|
|
1523
|
+
PH2: column
|
|
1524
|
+
});
|
|
1525
|
+
};
|
|
1526
|
+
const typeNameofCommandToRun = () => {
|
|
1527
|
+
return i18nString(TypeNameOfCommandToRun);
|
|
1528
|
+
};
|
|
1529
|
+
const showAndRunCommands = () => {
|
|
1530
|
+
return i18nString(ShowAndRunCommands);
|
|
1531
|
+
};
|
|
1532
|
+
const goToFile = () => {
|
|
1533
|
+
return i18nString(GoToFile);
|
|
1534
|
+
};
|
|
1535
|
+
const noResults = () => {
|
|
1536
|
+
return i18nString(NoResults);
|
|
1537
|
+
};
|
|
1538
|
+
const quickOpen = () => {
|
|
1539
|
+
return i18nString(QuickOpen);
|
|
1540
|
+
};
|
|
1541
|
+
const goToLineColumn = () => {
|
|
1542
|
+
return i18nString(GoToLineColumn);
|
|
1543
|
+
};
|
|
1544
|
+
const goToSymbolInEditor = () => {
|
|
1545
|
+
return i18nString(GoToSymbolInEditor);
|
|
1546
|
+
};
|
|
1547
|
+
const searchForText = () => {
|
|
1548
|
+
return i18nString(SearchForText);
|
|
1549
|
+
};
|
|
1550
|
+
const openView = () => {
|
|
1551
|
+
return i18nString(OpenView);
|
|
1552
|
+
};
|
|
1553
|
+
|
|
1554
|
+
const getPicksGoToColumn = async value => {
|
|
1555
|
+
if (value === GoToColumn) {
|
|
1556
|
+
return getPicksGoToColumnBase();
|
|
1557
|
+
}
|
|
1558
|
+
if (value.startsWith(GoToColumn)) {
|
|
1559
|
+
const columnString = value.slice(GoToColumn.length);
|
|
1560
|
+
const wantedColumn = Number.parseInt(columnString, 10);
|
|
1561
|
+
if (Number.isNaN(wantedColumn)) {
|
|
1562
|
+
return getPicksGoToColumnBase();
|
|
1563
|
+
}
|
|
1564
|
+
const text = await getText();
|
|
1565
|
+
const position = getPosition(text, wantedColumn);
|
|
1566
|
+
return [{
|
|
1567
|
+
description: '',
|
|
1568
|
+
direntType: 0,
|
|
1569
|
+
fileIcon: '',
|
|
1570
|
+
icon: '',
|
|
1571
|
+
label: pressEnterToGoToLine(position.row, position.column),
|
|
1572
|
+
matches: [],
|
|
1573
|
+
uri: ''
|
|
1574
|
+
}];
|
|
1575
|
+
}
|
|
1576
|
+
return [];
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
const splitLines$2 = lines => {
|
|
1580
|
+
if (!lines) {
|
|
1581
|
+
return [];
|
|
1582
|
+
}
|
|
1583
|
+
return lines.split('\n');
|
|
1584
|
+
};
|
|
1585
|
+
|
|
1586
|
+
const getPicksGoToLineBase = async () => {
|
|
1587
|
+
const text = await getText();
|
|
1588
|
+
const lines = splitLines$2(text);
|
|
1589
|
+
const lineCount = lines.length;
|
|
1590
|
+
return [{
|
|
1591
|
+
description: '',
|
|
1592
|
+
direntType: 0,
|
|
1593
|
+
fileIcon: '',
|
|
1594
|
+
icon: '',
|
|
1595
|
+
label: `Type a line number to go to (from 1 to ${lineCount})`,
|
|
1596
|
+
matches: [],
|
|
1597
|
+
uri: ''
|
|
1598
|
+
}];
|
|
1599
|
+
};
|
|
1600
|
+
|
|
1601
|
+
const parseGotoline = value => {
|
|
1602
|
+
const lineString = value.slice(GoToLine$1.length);
|
|
1603
|
+
const wantedLine = Number.parseInt(lineString, 10);
|
|
1604
|
+
if (Number.isNaN(wantedLine)) {
|
|
1605
|
+
return -1;
|
|
1606
|
+
}
|
|
1607
|
+
return wantedLine;
|
|
1608
|
+
};
|
|
1609
|
+
|
|
1610
|
+
const getPicks$8 = async value => {
|
|
1611
|
+
if (value === GoToLine$1) {
|
|
1612
|
+
return getPicksGoToLineBase();
|
|
1613
|
+
}
|
|
1614
|
+
if (value.startsWith(GoToLine$1)) {
|
|
1615
|
+
const wantedLine = parseGotoline(value);
|
|
1616
|
+
if (wantedLine === -1) {
|
|
1617
|
+
return getPicksGoToLineBase();
|
|
1618
|
+
}
|
|
1619
|
+
const rowIndex = wantedLine - 1;
|
|
1620
|
+
const columnIndex = 0;
|
|
1621
|
+
return [{
|
|
1622
|
+
description: '',
|
|
1623
|
+
direntType: 0,
|
|
1624
|
+
fileIcon: '',
|
|
1625
|
+
icon: '',
|
|
1626
|
+
label: pressEnterToGoToLine(rowIndex, columnIndex),
|
|
1627
|
+
matches: [],
|
|
1628
|
+
uri: ''
|
|
1629
|
+
}];
|
|
1630
|
+
}
|
|
1631
|
+
return [];
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1634
|
+
const DotDotDot = '...';
|
|
1635
|
+
const Colon = ':';
|
|
1636
|
+
const Percent = '%';
|
|
1637
|
+
const AngleBracket = '>';
|
|
1638
|
+
const View$1 = 'view';
|
|
1639
|
+
|
|
1640
|
+
const getPicks$7 = async () => {
|
|
1641
|
+
return [{
|
|
1642
|
+
description: goToFile(),
|
|
1643
|
+
direntType: None$2,
|
|
1644
|
+
fileIcon: '',
|
|
1645
|
+
icon: '',
|
|
1646
|
+
label: DotDotDot,
|
|
1647
|
+
matches: [],
|
|
1648
|
+
uri: ''
|
|
1649
|
+
}, {
|
|
1650
|
+
description: goToLineColumn(),
|
|
1651
|
+
direntType: None$2,
|
|
1652
|
+
fileIcon: '',
|
|
1653
|
+
icon: '',
|
|
1654
|
+
label: ':',
|
|
1655
|
+
matches: [],
|
|
1656
|
+
uri: ''
|
|
1657
|
+
}, {
|
|
1658
|
+
description: goToSymbolInEditor(),
|
|
1659
|
+
direntType: None$2,
|
|
1660
|
+
fileIcon: '',
|
|
1661
|
+
icon: '',
|
|
1662
|
+
label: Colon,
|
|
1663
|
+
matches: [],
|
|
1664
|
+
uri: ''
|
|
1665
|
+
}, {
|
|
1666
|
+
description: searchForText(),
|
|
1667
|
+
direntType: None$2,
|
|
1668
|
+
fileIcon: '',
|
|
1669
|
+
icon: '',
|
|
1670
|
+
label: Percent,
|
|
1671
|
+
matches: [],
|
|
1672
|
+
uri: ''
|
|
1673
|
+
}, {
|
|
1674
|
+
description: showAndRunCommands(),
|
|
1675
|
+
direntType: None$2,
|
|
1676
|
+
fileIcon: '',
|
|
1677
|
+
icon: '',
|
|
1678
|
+
label: AngleBracket,
|
|
1679
|
+
matches: [],
|
|
1680
|
+
uri: ''
|
|
1681
|
+
}, {
|
|
1682
|
+
description: openView(),
|
|
1683
|
+
direntType: None$2,
|
|
1684
|
+
fileIcon: '',
|
|
1685
|
+
icon: '',
|
|
1686
|
+
label: View$1,
|
|
1687
|
+
matches: [],
|
|
1688
|
+
uri: ''
|
|
1689
|
+
}];
|
|
1690
|
+
};
|
|
1691
|
+
|
|
1692
|
+
const getRecentlyOpened = () => {
|
|
1693
|
+
return invoke$1(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
|
|
1694
|
+
};
|
|
1695
|
+
|
|
1696
|
+
const getLabel = uri => {
|
|
1697
|
+
if (uri.startsWith('file://')) {
|
|
1698
|
+
return uri.slice('file://'.length);
|
|
1699
|
+
}
|
|
1700
|
+
return uri;
|
|
1701
|
+
};
|
|
1702
|
+
const toProtoVisibleItem = uri => {
|
|
1703
|
+
return {
|
|
1704
|
+
description: '',
|
|
1705
|
+
direntType: Directory,
|
|
1706
|
+
fileIcon: '',
|
|
1707
|
+
icon: '',
|
|
1708
|
+
label: getLabel(uri),
|
|
1709
|
+
matches: [],
|
|
1710
|
+
uri
|
|
1711
|
+
};
|
|
1712
|
+
};
|
|
1713
|
+
const getPicks$6 = async () => {
|
|
1714
|
+
const recentlyOpened = await getRecentlyOpened();
|
|
1715
|
+
const picks = recentlyOpened.map(toProtoVisibleItem);
|
|
1716
|
+
return picks;
|
|
1717
|
+
};
|
|
1718
|
+
|
|
1719
|
+
const getPicks$5 = async () => {
|
|
1720
|
+
const picks = [];
|
|
1721
|
+
return picks;
|
|
1722
|
+
};
|
|
1723
|
+
|
|
1724
|
+
const getPicks$4 = async () => {
|
|
1725
|
+
return [];
|
|
1726
|
+
};
|
|
1727
|
+
|
|
1728
|
+
const getPicks$3 = async () => {
|
|
1729
|
+
const picks = [];
|
|
1730
|
+
return picks;
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1733
|
+
const Hide = 'hide';
|
|
1734
|
+
const KeepOpen = '';
|
|
1735
|
+
|
|
1736
|
+
const selectPick$9 = async pick => {
|
|
1737
|
+
const id = pick.label;
|
|
1738
|
+
await setColorTheme(id);
|
|
1739
|
+
return {
|
|
1740
|
+
command: Hide
|
|
1741
|
+
};
|
|
1742
|
+
};
|
|
1743
|
+
|
|
1744
|
+
const hideIds = ['AutoUpdater.checkForUpdates'];
|
|
1745
|
+
const shouldHide = item => {
|
|
1746
|
+
if (hideIds.includes(item.id)) {
|
|
1747
|
+
return false;
|
|
1748
|
+
}
|
|
1749
|
+
if (item.id === 'Viewlet.openWidget' && item.args?.[0] === 'QuickPick') {
|
|
1750
|
+
return false;
|
|
1751
|
+
}
|
|
1752
|
+
return true;
|
|
1753
|
+
};
|
|
1754
|
+
|
|
1755
|
+
const selectPickBuiltin = async item => {
|
|
1756
|
+
const args = item.args || [];
|
|
1757
|
+
// TODO ids should be all numbers for efficiency -> also directly can call command
|
|
1758
|
+
await invoke$1(item.id, ...args);
|
|
1759
|
+
if (shouldHide(item)) {
|
|
1760
|
+
return {
|
|
1761
|
+
command: Hide
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
return {
|
|
1765
|
+
command: KeepOpen
|
|
1766
|
+
};
|
|
1767
|
+
};
|
|
1768
|
+
const selectPickExtension = async item => {
|
|
1769
|
+
const id = item.id.slice(4); // TODO lots of string allocation with 'ext.' find a better way to separate builtin commands from extension commands
|
|
1770
|
+
try {
|
|
1771
|
+
await invoke$1('ExtensionHost.executeCommand', id);
|
|
1772
|
+
} catch (error) {
|
|
1773
|
+
await handleError(error, false);
|
|
1774
|
+
await showErrorDialog(error);
|
|
1775
|
+
}
|
|
1776
|
+
return {
|
|
1777
|
+
command: Hide
|
|
1778
|
+
};
|
|
1779
|
+
};
|
|
1780
|
+
const selectPick$8 = async item => {
|
|
1781
|
+
// @ts-ignore
|
|
1782
|
+
const {
|
|
1783
|
+
id
|
|
1784
|
+
} = item;
|
|
1785
|
+
if (id.startsWith('ext.')) {
|
|
1786
|
+
return selectPickExtension(item);
|
|
1787
|
+
}
|
|
1788
|
+
return selectPickBuiltin(item);
|
|
1789
|
+
};
|
|
1790
|
+
|
|
1791
|
+
const state = {
|
|
1792
|
+
args: []
|
|
1793
|
+
};
|
|
1794
|
+
|
|
1795
|
+
const selectPick$7 = async pick => {
|
|
1796
|
+
const {
|
|
1797
|
+
args
|
|
1798
|
+
} = state;
|
|
1799
|
+
const resolveId = args[2];
|
|
1800
|
+
await invoke$1(`QuickPick.executeCallback`, resolveId, pick);
|
|
1801
|
+
return {
|
|
1802
|
+
command: Hide
|
|
1803
|
+
};
|
|
1804
|
+
};
|
|
1805
|
+
|
|
1806
|
+
const openUri = async uri => {
|
|
1807
|
+
await openUri$1(uri);
|
|
1808
|
+
};
|
|
1809
|
+
|
|
1810
|
+
const selectPick$6 = async pick => {
|
|
1811
|
+
const {
|
|
1812
|
+
description
|
|
1813
|
+
} = pick;
|
|
1814
|
+
const fileName = pick.label;
|
|
1815
|
+
const workspace = await getWorkspacePath();
|
|
1816
|
+
const absolutePath = `${workspace}/${description}/${fileName}`;
|
|
1817
|
+
await openUri(absolutePath);
|
|
1818
|
+
return {
|
|
1819
|
+
command: Hide
|
|
1820
|
+
};
|
|
1821
|
+
};
|
|
1822
|
+
|
|
1823
|
+
const setCursor = async (rowIndex, columnIndex) => {
|
|
1824
|
+
await invoke$1('Editor.cursorSet', rowIndex, columnIndex);
|
|
1825
|
+
};
|
|
1826
|
+
|
|
1827
|
+
const goToPositionAndFocus = async (rowIndex, columnIndex) => {
|
|
1828
|
+
await setCursor(rowIndex, columnIndex);
|
|
1829
|
+
await invoke$1('Editor.handleFocus');
|
|
1830
|
+
};
|
|
1831
|
+
|
|
1832
|
+
const selectPickGoToColumn = async (item, value) => {
|
|
1833
|
+
if (value.startsWith(GoToColumn)) {
|
|
1834
|
+
const columnString = value.slice(2);
|
|
1835
|
+
const wantedColumn = Number.parseInt(columnString, 10);
|
|
1836
|
+
const text = await getText();
|
|
1837
|
+
const position = getPosition(text, wantedColumn);
|
|
1838
|
+
await goToPositionAndFocus(position.row, position.column);
|
|
1839
|
+
return {
|
|
1840
|
+
command: Hide
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
return {
|
|
1844
|
+
command: Hide
|
|
1845
|
+
};
|
|
1846
|
+
};
|
|
1847
|
+
|
|
1848
|
+
const selectPick$5 = async (item, value) => {
|
|
1849
|
+
if (value.startsWith(GoToLine$1)) {
|
|
1850
|
+
const lineString = value.slice(GoToLine$1.length);
|
|
1851
|
+
const wantedLine = Number.parseInt(lineString, 10);
|
|
1852
|
+
const rowIndex = wantedLine - 1;
|
|
1853
|
+
const columnIndex = 0;
|
|
1854
|
+
await goToPositionAndFocus(rowIndex, columnIndex);
|
|
1855
|
+
return {
|
|
1856
|
+
command: Hide
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
return {
|
|
1860
|
+
command: Hide
|
|
1861
|
+
};
|
|
1862
|
+
};
|
|
1863
|
+
|
|
1864
|
+
const selectPick$4 = async item => {
|
|
1865
|
+
// Command.execute(/* openView */ 549, /* viewName */ item.label)
|
|
1866
|
+
return {
|
|
1867
|
+
command: Hide
|
|
1868
|
+
};
|
|
1869
|
+
};
|
|
1870
|
+
|
|
1871
|
+
const openWorkspaceFolder = uri => {
|
|
1872
|
+
return invoke$1(/* Workspace.setPath */'Workspace.setPath', /* path */uri);
|
|
1873
|
+
};
|
|
1874
|
+
|
|
1875
|
+
// TODO selectPick should be independent of show/hide
|
|
1876
|
+
const selectPick$3 = async pick => {
|
|
1877
|
+
const {
|
|
1878
|
+
uri
|
|
1879
|
+
} = pick;
|
|
1880
|
+
await openWorkspaceFolder(uri);
|
|
1881
|
+
return {
|
|
1882
|
+
command: Hide
|
|
1883
|
+
};
|
|
1884
|
+
};
|
|
1885
|
+
|
|
1886
|
+
const selectPick$2 = async item => {
|
|
1887
|
+
return {
|
|
1888
|
+
command: Hide
|
|
1889
|
+
};
|
|
1890
|
+
};
|
|
1891
|
+
|
|
1892
|
+
const selectPick$1 = async item => {
|
|
1893
|
+
// Command.execute(/* openView */ 549, /* viewName */ item.label)
|
|
1894
|
+
return {
|
|
1895
|
+
command: Hide
|
|
1896
|
+
};
|
|
1897
|
+
};
|
|
1898
|
+
|
|
1899
|
+
const selectPick = async item => {
|
|
1900
|
+
return {
|
|
1901
|
+
command: Hide
|
|
1902
|
+
};
|
|
1903
|
+
};
|
|
1904
|
+
|
|
1905
|
+
const selectPicks = [selectPick$9, selectPick$8, selectPick$7, selectPick$6, selectPickGoToColumn, selectPick$5, selectPick$4, selectPick$3, selectPick$2, selectPick$1, selectPick];
|
|
1906
|
+
const getPicks$2 = [getPicks$c, getPicks$b, getPicks$a, getPicks$9, getPicksGoToColumn, getPicks$8, getPicks$7, getPicks$6, getPicks$5, getPicks$4, getPicks$3];
|
|
1907
|
+
|
|
1908
|
+
const select = selectPicks;
|
|
1909
|
+
const getPick$1 = getPicks$2;
|
|
1910
|
+
const getPicks$1 = id => {
|
|
1911
|
+
const fn = getPick$1[id];
|
|
1912
|
+
return fn;
|
|
1913
|
+
};
|
|
1914
|
+
const getSelect = id => {
|
|
1915
|
+
const fn = select[id];
|
|
1916
|
+
return fn;
|
|
1917
|
+
};
|
|
1918
|
+
|
|
1919
|
+
const getPicks = (id, searchValue, args, {
|
|
1920
|
+
assetDir,
|
|
1921
|
+
platform
|
|
1922
|
+
}) => {
|
|
1923
|
+
const fn = getPicks$1(id);
|
|
1924
|
+
return fn(searchValue, args, {
|
|
1925
|
+
assetDir,
|
|
1926
|
+
platform
|
|
1927
|
+
});
|
|
1928
|
+
};
|
|
1929
|
+
|
|
1930
|
+
const getQuickPickSubProviderId = (id, prefix) => {
|
|
1931
|
+
if (id !== EveryThing$1) {
|
|
1932
|
+
return id;
|
|
1933
|
+
}
|
|
1934
|
+
switch (prefix) {
|
|
1935
|
+
case Command:
|
|
1936
|
+
return Commands$1;
|
|
1937
|
+
case GoToColumn:
|
|
1938
|
+
return GoToColumn$1;
|
|
1939
|
+
case GoToLine$1:
|
|
1940
|
+
return GoToLine$2;
|
|
1941
|
+
case Help$1:
|
|
1942
|
+
return Help$2;
|
|
1943
|
+
case Symbol$2:
|
|
1944
|
+
return Symbol$3;
|
|
1945
|
+
case View$2:
|
|
1946
|
+
return View$3;
|
|
1947
|
+
case WorkspaceSymbol$1:
|
|
1948
|
+
return WorkspaceSymbol$2;
|
|
1949
|
+
default:
|
|
1950
|
+
return File$2;
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
|
|
1954
|
+
// TODO when user types letters -> no need to query provider again -> just filter existing results
|
|
1955
|
+
const setValue = async (state, newValue) => {
|
|
1956
|
+
const {
|
|
1957
|
+
args,
|
|
1958
|
+
assetDir,
|
|
1959
|
+
fileIconCache,
|
|
1960
|
+
height,
|
|
1961
|
+
itemHeight,
|
|
1962
|
+
maxLineY,
|
|
1963
|
+
minLineY,
|
|
1964
|
+
platform,
|
|
1965
|
+
providerId,
|
|
1966
|
+
value
|
|
1967
|
+
} = state;
|
|
1968
|
+
if (value === newValue) {
|
|
1969
|
+
return state;
|
|
1970
|
+
}
|
|
1971
|
+
const prefix = getQuickPickPrefix(newValue);
|
|
1972
|
+
const subId = getQuickPickSubProviderId(providerId, prefix);
|
|
1973
|
+
const newPicks = await getPicks(subId, newValue, args, {
|
|
1974
|
+
assetDir,
|
|
1975
|
+
platform
|
|
1976
|
+
});
|
|
1977
|
+
const filterValue = getFilterValue(providerId, subId, newValue);
|
|
1978
|
+
const items = filterQuickPickItems(newPicks, filterValue);
|
|
1979
|
+
const focusedIndex = items.length === 0 ? -1 : 0;
|
|
1980
|
+
const sliced = items.slice(minLineY, maxLineY);
|
|
1981
|
+
const {
|
|
1982
|
+
icons,
|
|
1983
|
+
newFileIconCache
|
|
1984
|
+
} = await getQuickPickFileIcons(sliced, fileIconCache);
|
|
1985
|
+
const listHeight = getListHeight(items.length, itemHeight, height);
|
|
1986
|
+
const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, items.length);
|
|
1987
|
+
return {
|
|
1988
|
+
...state,
|
|
1989
|
+
fileIconCache: newFileIconCache,
|
|
1990
|
+
finalDeltaY,
|
|
1991
|
+
focusedIndex,
|
|
1992
|
+
icons,
|
|
1993
|
+
inputSource: Script,
|
|
1994
|
+
items,
|
|
1995
|
+
picks: newPicks,
|
|
1996
|
+
value: newValue
|
|
1997
|
+
};
|
|
1998
|
+
};
|
|
1999
|
+
|
|
2000
|
+
// TODO when user types letters -> no need to query provider again -> just filter existing results
|
|
2001
|
+
const handleInput = async (state, newValue, cursorOffset, inputSource = Script) => {
|
|
2002
|
+
if (state.value === newValue) {
|
|
2003
|
+
return {
|
|
2004
|
+
...state,
|
|
2005
|
+
cursorOffset,
|
|
2006
|
+
inputSource
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
2009
|
+
const newState = await setValue(state, newValue);
|
|
2010
|
+
return {
|
|
2011
|
+
...newState,
|
|
2012
|
+
cursorOffset,
|
|
2013
|
+
inputSource
|
|
2014
|
+
};
|
|
2015
|
+
};
|
|
2016
|
+
|
|
2017
|
+
const handleBeforeInput = (state, inputType, data, selectionStart, selectionEnd) => {
|
|
2018
|
+
string(inputType);
|
|
2019
|
+
number(selectionStart);
|
|
2020
|
+
number(selectionEnd);
|
|
2021
|
+
const {
|
|
2022
|
+
value
|
|
2023
|
+
} = state;
|
|
2024
|
+
const {
|
|
2025
|
+
cursorOffset,
|
|
2026
|
+
newValue
|
|
2027
|
+
} = getNewValue(value, inputType, data, selectionStart, selectionEnd);
|
|
2028
|
+
return handleInput(state, newValue, cursorOffset, User);
|
|
2029
|
+
};
|
|
2030
|
+
|
|
2031
|
+
const handleBlur = async state => {
|
|
2032
|
+
// TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
|
|
2033
|
+
// await CloseWidget.closeWidget(state.uid)
|
|
2034
|
+
return state;
|
|
2035
|
+
};
|
|
2036
|
+
|
|
2037
|
+
const getIndex = (top, headerHeight, itemHeight, y) => {
|
|
2038
|
+
const relativeY = y - top - headerHeight;
|
|
2039
|
+
const index = Math.floor(relativeY / itemHeight);
|
|
2040
|
+
return index;
|
|
2041
|
+
};
|
|
2042
|
+
|
|
2043
|
+
const getPick = (items, index) => {
|
|
2044
|
+
array(items);
|
|
2045
|
+
number(index);
|
|
2046
|
+
// if (index < state.recentPicks.length) {
|
|
2047
|
+
// return state.recentPicks[index]
|
|
2048
|
+
// }
|
|
2049
|
+
// index -= state.recentPicks.length
|
|
2050
|
+
if (index < items.length) {
|
|
2051
|
+
return items[index];
|
|
2052
|
+
}
|
|
2053
|
+
console.warn('no pick matching index', index);
|
|
2054
|
+
return undefined;
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
const selectIndex = async (state, index, button = /* left */0) => {
|
|
2058
|
+
const {
|
|
2059
|
+
items,
|
|
2060
|
+
minLineY,
|
|
2061
|
+
providerId,
|
|
2062
|
+
value
|
|
2063
|
+
} = state;
|
|
2064
|
+
const actualIndex = index + minLineY;
|
|
2065
|
+
const pick = getPick(items, actualIndex);
|
|
2066
|
+
if (!pick) {
|
|
2067
|
+
return state;
|
|
2068
|
+
}
|
|
2069
|
+
const prefix = getQuickPickPrefix(value);
|
|
2070
|
+
const subId = getQuickPickSubProviderId(providerId, prefix);
|
|
2071
|
+
const fn = getSelect(subId);
|
|
2072
|
+
const selectPickResult = await fn(pick, value);
|
|
2073
|
+
object(selectPickResult);
|
|
2074
|
+
string(selectPickResult.command);
|
|
2075
|
+
const {
|
|
2076
|
+
command
|
|
2077
|
+
} = selectPickResult;
|
|
2078
|
+
switch (command) {
|
|
2079
|
+
case Hide:
|
|
2080
|
+
await closeWidget(state.uid);
|
|
2081
|
+
return state;
|
|
2082
|
+
default:
|
|
2083
|
+
return state;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
// TODO recent picks should be per provider
|
|
2087
|
+
// if (!state.recentPickIds.has(pick.id)) {
|
|
2088
|
+
// state.recentPicks.unshift(pick)
|
|
2089
|
+
// state.recentPickIds.add(pick.id)
|
|
2090
|
+
// }
|
|
2091
|
+
// if (state.recentPicks.length > RECENT_PICKS_MAX_SIZE) {
|
|
2092
|
+
// const last = state.recentPicks.pop()
|
|
2093
|
+
// state.recentPickIds.delete(last.id)
|
|
2094
|
+
// }
|
|
2095
|
+
};
|
|
2096
|
+
|
|
2097
|
+
const handleClickAt = (state, x, y) => {
|
|
2098
|
+
const {
|
|
2099
|
+
headerHeight,
|
|
2100
|
+
itemHeight,
|
|
2101
|
+
top
|
|
2102
|
+
} = state;
|
|
2103
|
+
const index = getIndex(top, headerHeight, itemHeight, y);
|
|
2104
|
+
return selectIndex(state, index);
|
|
2105
|
+
};
|
|
2106
|
+
|
|
2107
|
+
const handleFocus = async state => {
|
|
2108
|
+
// TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
|
|
2109
|
+
await setFocus(FocusQuickPickInput);
|
|
2110
|
+
// await CloseWidget.closeWidget(state.uid)
|
|
2111
|
+
return state;
|
|
2112
|
+
};
|
|
2113
|
+
|
|
2114
|
+
const isMessagePort = value => {
|
|
2115
|
+
return value && value instanceof MessagePort;
|
|
2116
|
+
};
|
|
2117
|
+
const isMessagePortMain = value => {
|
|
2118
|
+
return value && value.constructor && value.constructor.name === 'MessagePortMain';
|
|
2119
|
+
};
|
|
2120
|
+
const isOffscreenCanvas = value => {
|
|
2121
|
+
return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
|
|
2122
|
+
};
|
|
2123
|
+
const isInstanceOf = (value, constructorName) => {
|
|
2124
|
+
return value?.constructor?.name === constructorName;
|
|
2125
|
+
};
|
|
2126
|
+
const isSocket = value => {
|
|
2127
|
+
return isInstanceOf(value, 'Socket');
|
|
2128
|
+
};
|
|
2129
|
+
const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
|
|
2130
|
+
const isTransferrable = value => {
|
|
2131
|
+
for (const fn of transferrables) {
|
|
2132
|
+
if (fn(value)) {
|
|
2133
|
+
return true;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
return false;
|
|
2137
|
+
};
|
|
2138
|
+
const walkValue = (value, transferrables, isTransferrable) => {
|
|
2139
|
+
if (!value) {
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
if (isTransferrable(value)) {
|
|
2143
|
+
transferrables.push(value);
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2146
|
+
if (Array.isArray(value)) {
|
|
2147
|
+
for (const item of value) {
|
|
2148
|
+
walkValue(item, transferrables, isTransferrable);
|
|
2149
|
+
}
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
if (typeof value === 'object') {
|
|
2153
|
+
for (const property of Object.values(value)) {
|
|
2154
|
+
walkValue(property, transferrables, isTransferrable);
|
|
2155
|
+
}
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
const getTransferrables = value => {
|
|
2160
|
+
const transferrables = [];
|
|
2161
|
+
walkValue(value, transferrables, isTransferrable);
|
|
2162
|
+
return transferrables;
|
|
2163
|
+
};
|
|
2164
|
+
const attachEvents = that => {
|
|
2165
|
+
const handleMessage = (...args) => {
|
|
2166
|
+
const data = that.getData(...args);
|
|
2167
|
+
that.dispatchEvent(new MessageEvent('message', {
|
|
2168
|
+
data
|
|
2169
|
+
}));
|
|
2170
|
+
};
|
|
2171
|
+
that.onMessage(handleMessage);
|
|
2172
|
+
const handleClose = event => {
|
|
2173
|
+
that.dispatchEvent(new Event('close'));
|
|
2174
|
+
};
|
|
2175
|
+
that.onClose(handleClose);
|
|
2176
|
+
};
|
|
2177
|
+
class Ipc extends EventTarget {
|
|
2178
|
+
constructor(rawIpc) {
|
|
2179
|
+
super();
|
|
2180
|
+
this._rawIpc = rawIpc;
|
|
2181
|
+
attachEvents(this);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
|
|
2185
|
+
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
|
|
2186
|
+
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
|
|
2187
|
+
const NewLine$1 = '\n';
|
|
2188
|
+
const joinLines$1 = lines => {
|
|
2189
|
+
return lines.join(NewLine$1);
|
|
2190
|
+
};
|
|
2191
|
+
const RE_AT = /^\s+at/;
|
|
2192
|
+
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
|
|
2193
|
+
const isNormalStackLine = line => {
|
|
2194
|
+
return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
|
|
2195
|
+
};
|
|
2196
|
+
const getDetails = lines => {
|
|
2197
|
+
const index = lines.findIndex(isNormalStackLine);
|
|
2198
|
+
if (index === -1) {
|
|
2199
|
+
return {
|
|
2200
|
+
actualMessage: joinLines$1(lines),
|
|
2201
|
+
rest: []
|
|
2202
|
+
};
|
|
2203
|
+
}
|
|
2204
|
+
let lastIndex = index - 1;
|
|
2205
|
+
while (++lastIndex < lines.length) {
|
|
2206
|
+
if (!isNormalStackLine(lines[lastIndex])) {
|
|
2207
|
+
break;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
return {
|
|
2211
|
+
actualMessage: lines[index - 1],
|
|
2212
|
+
rest: lines.slice(index, lastIndex)
|
|
2213
|
+
};
|
|
2214
|
+
};
|
|
2215
|
+
const splitLines$1 = lines => {
|
|
2216
|
+
return lines.split(NewLine$1);
|
|
2217
|
+
};
|
|
2218
|
+
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
|
|
2219
|
+
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
|
|
2220
|
+
const isMessageCodeBlockStartIndex = line => {
|
|
2221
|
+
return RE_MESSAGE_CODE_BLOCK_START.test(line);
|
|
2222
|
+
};
|
|
2223
|
+
const isMessageCodeBlockEndIndex = line => {
|
|
2224
|
+
return RE_MESSAGE_CODE_BLOCK_END.test(line);
|
|
2225
|
+
};
|
|
2226
|
+
const getMessageCodeBlock = stderr => {
|
|
2227
|
+
const lines = splitLines$1(stderr);
|
|
2228
|
+
const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
|
|
2229
|
+
const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
|
|
2230
|
+
const relevantLines = lines.slice(startIndex, endIndex);
|
|
2231
|
+
const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
|
|
2232
|
+
return relevantMessage;
|
|
2233
|
+
};
|
|
2234
|
+
const isModuleNotFoundMessage = line => {
|
|
2235
|
+
return line.includes('[ERR_MODULE_NOT_FOUND]');
|
|
2236
|
+
};
|
|
2237
|
+
const getModuleNotFoundError = stderr => {
|
|
2238
|
+
const lines = splitLines$1(stderr);
|
|
2239
|
+
const messageIndex = lines.findIndex(isModuleNotFoundMessage);
|
|
2240
|
+
const message = lines[messageIndex];
|
|
2241
|
+
return {
|
|
2242
|
+
code: ERR_MODULE_NOT_FOUND,
|
|
2243
|
+
message
|
|
2244
|
+
};
|
|
2245
|
+
};
|
|
2246
|
+
const isModuleNotFoundError = stderr => {
|
|
2247
|
+
if (!stderr) {
|
|
2248
|
+
return false;
|
|
2249
|
+
}
|
|
2250
|
+
return stderr.includes('ERR_MODULE_NOT_FOUND');
|
|
2251
|
+
};
|
|
2252
|
+
const isModulesSyntaxError = stderr => {
|
|
2253
|
+
if (!stderr) {
|
|
2254
|
+
return false;
|
|
2255
|
+
}
|
|
2256
|
+
return stderr.includes('SyntaxError: Cannot use import statement outside a module');
|
|
2257
|
+
};
|
|
2258
|
+
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
|
|
2259
|
+
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
|
|
2260
|
+
const isUnhelpfulNativeModuleError = stderr => {
|
|
2261
|
+
return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
|
|
2262
|
+
};
|
|
2263
|
+
const getNativeModuleErrorMessage = stderr => {
|
|
2264
|
+
const message = getMessageCodeBlock(stderr);
|
|
2265
|
+
return {
|
|
2266
|
+
code: E_INCOMPATIBLE_NATIVE_MODULE,
|
|
2267
|
+
message: `Incompatible native node module: ${message}`
|
|
2268
|
+
};
|
|
2269
|
+
};
|
|
2270
|
+
const getModuleSyntaxError = () => {
|
|
2271
|
+
return {
|
|
2272
|
+
code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON,
|
|
2273
|
+
message: `ES Modules are not supported in electron`
|
|
2274
|
+
};
|
|
2275
|
+
};
|
|
2276
|
+
const getHelpfulChildProcessError = (stdout, stderr) => {
|
|
2277
|
+
if (isUnhelpfulNativeModuleError(stderr)) {
|
|
2278
|
+
return getNativeModuleErrorMessage(stderr);
|
|
2279
|
+
}
|
|
2280
|
+
if (isModulesSyntaxError(stderr)) {
|
|
2281
|
+
return getModuleSyntaxError();
|
|
2282
|
+
}
|
|
2283
|
+
if (isModuleNotFoundError(stderr)) {
|
|
2284
|
+
return getModuleNotFoundError(stderr);
|
|
2285
|
+
}
|
|
2286
|
+
const lines = splitLines$1(stderr);
|
|
2287
|
+
const {
|
|
2288
|
+
actualMessage,
|
|
2289
|
+
rest
|
|
2290
|
+
} = getDetails(lines);
|
|
2291
|
+
return {
|
|
2292
|
+
code: '',
|
|
2293
|
+
message: actualMessage,
|
|
2294
|
+
stack: rest
|
|
2295
|
+
};
|
|
2296
|
+
};
|
|
2297
|
+
class IpcError extends VError {
|
|
2298
|
+
// @ts-ignore
|
|
2299
|
+
constructor(betterMessage, stdout = '', stderr = '') {
|
|
2300
|
+
if (stdout || stderr) {
|
|
2301
|
+
// @ts-ignore
|
|
2302
|
+
const {
|
|
2303
|
+
code,
|
|
2304
|
+
message,
|
|
2305
|
+
stack
|
|
2306
|
+
} = getHelpfulChildProcessError(stdout, stderr);
|
|
2307
|
+
const cause = new Error(message);
|
|
2308
|
+
// @ts-ignore
|
|
2309
|
+
cause.code = code;
|
|
2310
|
+
cause.stack = stack;
|
|
2311
|
+
super(cause, betterMessage);
|
|
2312
|
+
} else {
|
|
2313
|
+
super(betterMessage);
|
|
2314
|
+
}
|
|
2315
|
+
// @ts-ignore
|
|
2316
|
+
this.name = 'IpcError';
|
|
2317
|
+
// @ts-ignore
|
|
2318
|
+
this.stdout = stdout;
|
|
2319
|
+
// @ts-ignore
|
|
2320
|
+
this.stderr = stderr;
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
const readyMessage = 'ready';
|
|
2324
|
+
const getData$2 = event => {
|
|
2325
|
+
return event.data;
|
|
2326
|
+
};
|
|
2327
|
+
const listen$7 = () => {
|
|
2328
|
+
// @ts-ignore
|
|
2329
|
+
if (typeof WorkerGlobalScope === 'undefined') {
|
|
2330
|
+
throw new TypeError('module is not in web worker scope');
|
|
2331
|
+
}
|
|
2332
|
+
return globalThis;
|
|
2333
|
+
};
|
|
2334
|
+
const signal$8 = global => {
|
|
2335
|
+
global.postMessage(readyMessage);
|
|
2336
|
+
};
|
|
2337
|
+
class IpcChildWithModuleWorker extends Ipc {
|
|
2338
|
+
getData(event) {
|
|
2339
|
+
return getData$2(event);
|
|
2340
|
+
}
|
|
2341
|
+
send(message) {
|
|
2342
|
+
// @ts-ignore
|
|
2343
|
+
this._rawIpc.postMessage(message);
|
|
2344
|
+
}
|
|
2345
|
+
sendAndTransfer(message) {
|
|
2346
|
+
const transfer = getTransferrables(message);
|
|
2347
|
+
// @ts-ignore
|
|
2348
|
+
this._rawIpc.postMessage(message, transfer);
|
|
2349
|
+
}
|
|
2350
|
+
dispose() {
|
|
2351
|
+
// ignore
|
|
2352
|
+
}
|
|
2353
|
+
onClose(callback) {
|
|
2354
|
+
// ignore
|
|
2355
|
+
}
|
|
2356
|
+
onMessage(callback) {
|
|
2357
|
+
this._rawIpc.addEventListener('message', callback);
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
const wrap$f = global => {
|
|
2361
|
+
return new IpcChildWithModuleWorker(global);
|
|
2362
|
+
};
|
|
2363
|
+
const waitForFirstMessage = async port => {
|
|
2364
|
+
const {
|
|
2365
|
+
promise,
|
|
2366
|
+
resolve
|
|
2367
|
+
} = Promise.withResolvers();
|
|
2368
|
+
port.addEventListener('message', resolve, {
|
|
2369
|
+
once: true
|
|
2370
|
+
});
|
|
2371
|
+
const event = await promise;
|
|
2372
|
+
// @ts-ignore
|
|
2373
|
+
return event.data;
|
|
2374
|
+
};
|
|
2375
|
+
const listen$6 = async () => {
|
|
2376
|
+
const parentIpcRaw = listen$7();
|
|
2377
|
+
signal$8(parentIpcRaw);
|
|
2378
|
+
const parentIpc = wrap$f(parentIpcRaw);
|
|
2379
|
+
const firstMessage = await waitForFirstMessage(parentIpc);
|
|
2380
|
+
if (firstMessage.method !== 'initialize') {
|
|
2381
|
+
throw new IpcError('unexpected first message');
|
|
2382
|
+
}
|
|
2383
|
+
const type = firstMessage.params[0];
|
|
2384
|
+
if (type === 'message-port') {
|
|
2385
|
+
parentIpc.send({
|
|
2386
|
+
id: firstMessage.id,
|
|
2387
|
+
jsonrpc: '2.0',
|
|
2388
|
+
result: null
|
|
2389
|
+
});
|
|
2390
|
+
parentIpc.dispose();
|
|
2391
|
+
const port = firstMessage.params[1];
|
|
2392
|
+
return port;
|
|
2393
|
+
}
|
|
2394
|
+
return globalThis;
|
|
2395
|
+
};
|
|
2396
|
+
class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
|
|
2397
|
+
getData(event) {
|
|
2398
|
+
return getData$2(event);
|
|
2399
|
+
}
|
|
2400
|
+
send(message) {
|
|
2401
|
+
this._rawIpc.postMessage(message);
|
|
2402
|
+
}
|
|
2403
|
+
sendAndTransfer(message) {
|
|
2404
|
+
const transfer = getTransferrables(message);
|
|
2405
|
+
this._rawIpc.postMessage(message, transfer);
|
|
2406
|
+
}
|
|
2407
|
+
dispose() {
|
|
2408
|
+
if (this._rawIpc.close) {
|
|
2409
|
+
this._rawIpc.close();
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
onClose(callback) {
|
|
2413
|
+
// ignore
|
|
2414
|
+
}
|
|
2415
|
+
onMessage(callback) {
|
|
2416
|
+
this._rawIpc.addEventListener('message', callback);
|
|
2417
|
+
this._rawIpc.start();
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
const wrap$e = port => {
|
|
2421
|
+
return new IpcChildWithModuleWorkerAndMessagePort(port);
|
|
2422
|
+
};
|
|
2423
|
+
const IpcChildWithModuleWorkerAndMessagePort$1 = {
|
|
2424
|
+
__proto__: null,
|
|
2425
|
+
listen: listen$6,
|
|
2426
|
+
wrap: wrap$e
|
|
2427
|
+
};
|
|
2428
|
+
const addListener = (emitter, type, callback) => {
|
|
2429
|
+
if ('addEventListener' in emitter) {
|
|
2430
|
+
emitter.addEventListener(type, callback);
|
|
2431
|
+
} else {
|
|
2432
|
+
emitter.on(type, callback);
|
|
2433
|
+
}
|
|
2434
|
+
};
|
|
2435
|
+
const removeListener = (emitter, type, callback) => {
|
|
2436
|
+
if ('removeEventListener' in emitter) {
|
|
2437
|
+
emitter.removeEventListener(type, callback);
|
|
2438
|
+
} else {
|
|
2439
|
+
emitter.off(type, callback);
|
|
2440
|
+
}
|
|
2441
|
+
};
|
|
2442
|
+
const getFirstEvent = (eventEmitter, eventMap) => {
|
|
2443
|
+
const {
|
|
2444
|
+
promise,
|
|
2445
|
+
resolve
|
|
2446
|
+
} = Promise.withResolvers();
|
|
2447
|
+
const listenerMap = Object.create(null);
|
|
2448
|
+
const cleanup = value => {
|
|
2449
|
+
for (const event of Object.keys(eventMap)) {
|
|
2450
|
+
removeListener(eventEmitter, event, listenerMap[event]);
|
|
2451
|
+
}
|
|
2452
|
+
resolve(value);
|
|
2453
|
+
};
|
|
2454
|
+
for (const [event, type] of Object.entries(eventMap)) {
|
|
2455
|
+
const listener = event => {
|
|
2456
|
+
cleanup({
|
|
2457
|
+
event,
|
|
2458
|
+
type
|
|
2459
|
+
});
|
|
2460
|
+
};
|
|
2461
|
+
addListener(eventEmitter, event, listener);
|
|
2462
|
+
listenerMap[event] = listener;
|
|
2463
|
+
}
|
|
2464
|
+
return promise;
|
|
2465
|
+
};
|
|
2466
|
+
const Message$1 = 3;
|
|
2467
|
+
const create$5$1 = async ({
|
|
2468
|
+
isMessagePortOpen,
|
|
2469
|
+
messagePort
|
|
2470
|
+
}) => {
|
|
2471
|
+
if (!isMessagePort(messagePort)) {
|
|
2472
|
+
throw new IpcError('port must be of type MessagePort');
|
|
2473
|
+
}
|
|
2474
|
+
if (isMessagePortOpen) {
|
|
2475
|
+
return messagePort;
|
|
2476
|
+
}
|
|
2477
|
+
const eventPromise = getFirstEvent(messagePort, {
|
|
2478
|
+
message: Message$1
|
|
2479
|
+
});
|
|
2480
|
+
messagePort.start();
|
|
2481
|
+
const {
|
|
2482
|
+
event,
|
|
2483
|
+
type
|
|
2484
|
+
} = await eventPromise;
|
|
2485
|
+
if (type !== Message$1) {
|
|
2486
|
+
throw new IpcError('Failed to wait for ipc message');
|
|
2487
|
+
}
|
|
2488
|
+
if (event.data !== readyMessage) {
|
|
2489
|
+
throw new IpcError('unexpected first message');
|
|
2490
|
+
}
|
|
2491
|
+
return messagePort;
|
|
2492
|
+
};
|
|
2493
|
+
const signal$1 = messagePort => {
|
|
2494
|
+
messagePort.start();
|
|
2495
|
+
};
|
|
2496
|
+
class IpcParentWithMessagePort extends Ipc {
|
|
2497
|
+
getData = getData$2;
|
|
2498
|
+
send(message) {
|
|
2499
|
+
this._rawIpc.postMessage(message);
|
|
2500
|
+
}
|
|
2501
|
+
sendAndTransfer(message) {
|
|
2502
|
+
const transfer = getTransferrables(message);
|
|
2503
|
+
this._rawIpc.postMessage(message, transfer);
|
|
2504
|
+
}
|
|
2505
|
+
dispose() {
|
|
2506
|
+
this._rawIpc.close();
|
|
2507
|
+
}
|
|
2508
|
+
onMessage(callback) {
|
|
2509
|
+
this._rawIpc.addEventListener('message', callback);
|
|
2510
|
+
}
|
|
2511
|
+
onClose(callback) {}
|
|
2512
|
+
}
|
|
2513
|
+
const wrap$5 = messagePort => {
|
|
2514
|
+
return new IpcParentWithMessagePort(messagePort);
|
|
2515
|
+
};
|
|
2516
|
+
const IpcParentWithMessagePort$1 = {
|
|
2517
|
+
__proto__: null,
|
|
2518
|
+
create: create$5$1,
|
|
2519
|
+
signal: signal$1,
|
|
2520
|
+
wrap: wrap$5
|
|
2521
|
+
};
|
|
2522
|
+
|
|
2523
|
+
const Two$1 = '2.0';
|
|
2524
|
+
const callbacks$1 = Object.create(null);
|
|
2525
|
+
const get = id => {
|
|
2526
|
+
return callbacks$1[id];
|
|
2527
|
+
};
|
|
2528
|
+
const remove = id => {
|
|
2529
|
+
delete callbacks$1[id];
|
|
2530
|
+
};
|
|
2531
|
+
class JsonRpcError extends Error {
|
|
2532
|
+
constructor(message) {
|
|
2533
|
+
super(message);
|
|
2534
|
+
this.name = 'JsonRpcError';
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
const NewLine = '\n';
|
|
2538
|
+
const DomException = 'DOMException';
|
|
2539
|
+
const ReferenceError$1 = 'ReferenceError';
|
|
2540
|
+
const SyntaxError$1 = 'SyntaxError';
|
|
2541
|
+
const TypeError$1 = 'TypeError';
|
|
2542
|
+
const getErrorConstructor = (message, type) => {
|
|
2543
|
+
if (type) {
|
|
2544
|
+
switch (type) {
|
|
2545
|
+
case DomException:
|
|
2546
|
+
return DOMException;
|
|
2547
|
+
case ReferenceError$1:
|
|
2548
|
+
return ReferenceError;
|
|
2549
|
+
case SyntaxError$1:
|
|
2550
|
+
return SyntaxError;
|
|
2551
|
+
case TypeError$1:
|
|
2552
|
+
return TypeError;
|
|
2553
|
+
default:
|
|
2554
|
+
return Error;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
if (message.startsWith('TypeError: ')) {
|
|
2558
|
+
return TypeError;
|
|
2559
|
+
}
|
|
2560
|
+
if (message.startsWith('SyntaxError: ')) {
|
|
2561
|
+
return SyntaxError;
|
|
2562
|
+
}
|
|
2563
|
+
if (message.startsWith('ReferenceError: ')) {
|
|
2564
|
+
return ReferenceError;
|
|
2565
|
+
}
|
|
2566
|
+
return Error;
|
|
2567
|
+
};
|
|
2568
|
+
const constructError = (message, type, name) => {
|
|
2569
|
+
const ErrorConstructor = getErrorConstructor(message, type);
|
|
2570
|
+
if (ErrorConstructor === DOMException && name) {
|
|
2571
|
+
return new ErrorConstructor(message, name);
|
|
2572
|
+
}
|
|
2573
|
+
if (ErrorConstructor === Error) {
|
|
2574
|
+
const error = new Error(message);
|
|
2575
|
+
if (name && name !== 'VError') {
|
|
2576
|
+
error.name = name;
|
|
2577
|
+
}
|
|
2578
|
+
return error;
|
|
2579
|
+
}
|
|
2580
|
+
return new ErrorConstructor(message);
|
|
2581
|
+
};
|
|
2582
|
+
const joinLines = lines => {
|
|
2583
|
+
return lines.join(NewLine);
|
|
2584
|
+
};
|
|
2585
|
+
const splitLines = lines => {
|
|
2586
|
+
return lines.split(NewLine);
|
|
2587
|
+
};
|
|
2588
|
+
const getCurrentStack = () => {
|
|
2589
|
+
const stackLinesToSkip = 3;
|
|
2590
|
+
const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip));
|
|
2591
|
+
return currentStack;
|
|
2592
|
+
};
|
|
2593
|
+
const getNewLineIndex = (string, startIndex = undefined) => {
|
|
2594
|
+
return string.indexOf(NewLine, startIndex);
|
|
2595
|
+
};
|
|
2596
|
+
const getParentStack = error => {
|
|
2597
|
+
let parentStack = error.stack || error.data || error.message || '';
|
|
2598
|
+
if (parentStack.startsWith(' at')) {
|
|
2599
|
+
parentStack = error.message + NewLine + parentStack;
|
|
2600
|
+
}
|
|
2601
|
+
return parentStack;
|
|
2602
|
+
};
|
|
2603
|
+
const MethodNotFound = -32601;
|
|
2604
|
+
const Custom$1 = -32001;
|
|
2605
|
+
const restoreJsonRpcError = error => {
|
|
2606
|
+
const currentStack = getCurrentStack();
|
|
2607
|
+
if (error && error instanceof Error) {
|
|
2608
|
+
if (typeof error.stack === 'string') {
|
|
2609
|
+
error.stack = error.stack + NewLine + currentStack;
|
|
2610
|
+
}
|
|
2611
|
+
return error;
|
|
2612
|
+
}
|
|
2613
|
+
if (error && error.code && error.code === MethodNotFound) {
|
|
2614
|
+
const restoredError = new JsonRpcError(error.message);
|
|
2615
|
+
const parentStack = getParentStack(error);
|
|
2616
|
+
restoredError.stack = parentStack + NewLine + currentStack;
|
|
2617
|
+
return restoredError;
|
|
2618
|
+
}
|
|
2619
|
+
if (error && error.message) {
|
|
2620
|
+
const restoredError = constructError(error.message, error.type, error.name);
|
|
2621
|
+
if (error.data) {
|
|
2622
|
+
if (error.data.stack && error.data.type && error.message) {
|
|
2623
|
+
restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
|
|
2624
|
+
} else if (error.data.stack) {
|
|
2625
|
+
restoredError.stack = error.data.stack;
|
|
2626
|
+
}
|
|
2627
|
+
if (error.data.codeFrame) {
|
|
2628
|
+
// @ts-ignore
|
|
2629
|
+
restoredError.codeFrame = error.data.codeFrame;
|
|
2630
|
+
}
|
|
2631
|
+
if (error.data.code) {
|
|
2632
|
+
// @ts-ignore
|
|
2633
|
+
restoredError.code = error.data.code;
|
|
2634
|
+
}
|
|
2635
|
+
if (error.data.type) {
|
|
2636
|
+
// @ts-ignore
|
|
2637
|
+
restoredError.name = error.data.type;
|
|
2638
|
+
}
|
|
2639
|
+
} else {
|
|
2640
|
+
if (error.stack) {
|
|
2641
|
+
const lowerStack = restoredError.stack || '';
|
|
2642
|
+
// @ts-ignore
|
|
2643
|
+
const indexNewLine = getNewLineIndex(lowerStack);
|
|
2644
|
+
const parentStack = getParentStack(error);
|
|
2645
|
+
// @ts-ignore
|
|
2646
|
+
restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
|
|
2647
|
+
}
|
|
2648
|
+
if (error.codeFrame) {
|
|
2649
|
+
// @ts-ignore
|
|
2650
|
+
restoredError.codeFrame = error.codeFrame;
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
return restoredError;
|
|
2654
|
+
}
|
|
2655
|
+
if (typeof error === 'string') {
|
|
2656
|
+
return new Error(`JsonRpc Error: ${error}`);
|
|
2657
|
+
}
|
|
2658
|
+
return new Error(`JsonRpc Error: ${error}`);
|
|
2659
|
+
};
|
|
2660
|
+
const unwrapJsonRpcResult = responseMessage => {
|
|
2661
|
+
if ('error' in responseMessage) {
|
|
2662
|
+
const restoredError = restoreJsonRpcError(responseMessage.error);
|
|
2663
|
+
throw restoredError;
|
|
2664
|
+
}
|
|
2665
|
+
if ('result' in responseMessage) {
|
|
2666
|
+
return responseMessage.result;
|
|
2667
|
+
}
|
|
2668
|
+
throw new JsonRpcError('unexpected response message');
|
|
2669
|
+
};
|
|
2670
|
+
const warn = (...args) => {
|
|
2671
|
+
console.warn(...args);
|
|
2672
|
+
};
|
|
2673
|
+
const resolve = (id, response) => {
|
|
2674
|
+
const fn = get(id);
|
|
2675
|
+
if (!fn) {
|
|
2676
|
+
console.log(response);
|
|
2677
|
+
warn(`callback ${id} may already be disposed`);
|
|
2678
|
+
return;
|
|
2679
|
+
}
|
|
2680
|
+
fn(response);
|
|
2681
|
+
remove(id);
|
|
2682
|
+
};
|
|
2683
|
+
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
|
|
2684
|
+
const getErrorType = prettyError => {
|
|
2685
|
+
if (prettyError && prettyError.type) {
|
|
2686
|
+
return prettyError.type;
|
|
2687
|
+
}
|
|
2688
|
+
if (prettyError && prettyError.constructor && prettyError.constructor.name) {
|
|
2689
|
+
return prettyError.constructor.name;
|
|
2690
|
+
}
|
|
2691
|
+
return undefined;
|
|
2692
|
+
};
|
|
2693
|
+
const isAlreadyStack = line => {
|
|
2694
|
+
return line.trim().startsWith('at ');
|
|
2695
|
+
};
|
|
2696
|
+
const getStack = prettyError => {
|
|
2697
|
+
const stackString = prettyError.stack || '';
|
|
2698
|
+
const newLineIndex = stackString.indexOf('\n');
|
|
2699
|
+
if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
|
|
2700
|
+
return stackString.slice(newLineIndex + 1);
|
|
2701
|
+
}
|
|
2702
|
+
return stackString;
|
|
2703
|
+
};
|
|
2704
|
+
const getErrorProperty = (error, prettyError) => {
|
|
2705
|
+
if (error && error.code === E_COMMAND_NOT_FOUND) {
|
|
2706
|
+
return {
|
|
2707
|
+
code: MethodNotFound,
|
|
2708
|
+
data: error.stack,
|
|
2709
|
+
message: error.message
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2712
|
+
return {
|
|
2713
|
+
code: Custom$1,
|
|
2714
|
+
data: {
|
|
2715
|
+
code: prettyError.code,
|
|
2716
|
+
codeFrame: prettyError.codeFrame,
|
|
2717
|
+
name: prettyError.name,
|
|
2718
|
+
stack: getStack(prettyError),
|
|
2719
|
+
type: getErrorType(prettyError)
|
|
2720
|
+
},
|
|
2721
|
+
message: prettyError.message
|
|
2722
|
+
};
|
|
2723
|
+
};
|
|
2724
|
+
const create$1$1 = (id, error) => {
|
|
2725
|
+
return {
|
|
2726
|
+
error,
|
|
2727
|
+
id,
|
|
2728
|
+
jsonrpc: Two$1
|
|
2729
|
+
};
|
|
2730
|
+
};
|
|
2731
|
+
const getErrorResponse = (id, error, preparePrettyError, logError) => {
|
|
2732
|
+
const prettyError = preparePrettyError(error);
|
|
2733
|
+
logError(error, prettyError);
|
|
2734
|
+
const errorProperty = getErrorProperty(error, prettyError);
|
|
2735
|
+
return create$1$1(id, errorProperty);
|
|
2736
|
+
};
|
|
2737
|
+
const create$7 = (message, result) => {
|
|
2738
|
+
return {
|
|
2739
|
+
id: message.id,
|
|
2740
|
+
jsonrpc: Two$1,
|
|
2741
|
+
result: result ?? null
|
|
2742
|
+
};
|
|
2743
|
+
};
|
|
2744
|
+
const getSuccessResponse = (message, result) => {
|
|
2745
|
+
const resultProperty = result ?? null;
|
|
2746
|
+
return create$7(message, resultProperty);
|
|
2747
|
+
};
|
|
2748
|
+
const getErrorResponseSimple = (id, error) => {
|
|
2749
|
+
return {
|
|
2750
|
+
error: {
|
|
2751
|
+
code: Custom$1,
|
|
2752
|
+
data: error,
|
|
2753
|
+
// @ts-ignore
|
|
2754
|
+
message: error.message
|
|
2755
|
+
},
|
|
2756
|
+
id,
|
|
2757
|
+
jsonrpc: Two$1
|
|
2758
|
+
};
|
|
2759
|
+
};
|
|
2760
|
+
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
|
|
2761
|
+
try {
|
|
2762
|
+
const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
|
|
2763
|
+
return getSuccessResponse(message, result);
|
|
2764
|
+
} catch (error) {
|
|
2765
|
+
if (ipc.canUseSimpleErrorResponse) {
|
|
2766
|
+
return getErrorResponseSimple(message.id, error);
|
|
2767
|
+
}
|
|
2768
|
+
return getErrorResponse(message.id, error, preparePrettyError, logError);
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
const defaultPreparePrettyError = error => {
|
|
2772
|
+
return error;
|
|
2773
|
+
};
|
|
2774
|
+
const defaultLogError = () => {
|
|
2775
|
+
// ignore
|
|
2776
|
+
};
|
|
2777
|
+
const defaultRequiresSocket = () => {
|
|
2778
|
+
return false;
|
|
2779
|
+
};
|
|
2780
|
+
const defaultResolve = resolve;
|
|
2781
|
+
|
|
2782
|
+
// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
|
|
2783
|
+
const normalizeParams = args => {
|
|
2784
|
+
if (args.length === 1) {
|
|
2785
|
+
const options = args[0];
|
|
2786
|
+
return {
|
|
2787
|
+
execute: options.execute,
|
|
2788
|
+
ipc: options.ipc,
|
|
2789
|
+
logError: options.logError || defaultLogError,
|
|
2790
|
+
message: options.message,
|
|
2791
|
+
preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
|
|
2792
|
+
requiresSocket: options.requiresSocket || defaultRequiresSocket,
|
|
2793
|
+
resolve: options.resolve || defaultResolve
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
return {
|
|
2797
|
+
execute: args[2],
|
|
2798
|
+
ipc: args[0],
|
|
2799
|
+
logError: args[5],
|
|
2800
|
+
message: args[1],
|
|
2801
|
+
preparePrettyError: args[4],
|
|
2802
|
+
requiresSocket: args[6],
|
|
2803
|
+
resolve: args[3]
|
|
2804
|
+
};
|
|
2805
|
+
};
|
|
2806
|
+
const handleJsonRpcMessage = async (...args) => {
|
|
2807
|
+
const options = normalizeParams(args);
|
|
2808
|
+
const {
|
|
2809
|
+
execute,
|
|
2810
|
+
ipc,
|
|
2811
|
+
logError,
|
|
2812
|
+
message,
|
|
2813
|
+
preparePrettyError,
|
|
2814
|
+
requiresSocket,
|
|
2815
|
+
resolve
|
|
2816
|
+
} = options;
|
|
2817
|
+
if ('id' in message) {
|
|
2818
|
+
if ('method' in message) {
|
|
2819
|
+
const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
|
|
2820
|
+
try {
|
|
2821
|
+
ipc.send(response);
|
|
2822
|
+
} catch (error) {
|
|
2823
|
+
const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
|
|
2824
|
+
ipc.send(errorResponse);
|
|
2825
|
+
}
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2828
|
+
resolve(message.id, message);
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
if ('method' in message) {
|
|
2832
|
+
await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
|
|
2833
|
+
return;
|
|
2834
|
+
}
|
|
2835
|
+
throw new JsonRpcError('unexpected message');
|
|
2836
|
+
};
|
|
2837
|
+
|
|
2838
|
+
const Two = '2.0';
|
|
2839
|
+
|
|
2840
|
+
const create$6 = (method, params) => {
|
|
2841
|
+
return {
|
|
2842
|
+
jsonrpc: Two,
|
|
2843
|
+
method,
|
|
2844
|
+
params
|
|
2845
|
+
};
|
|
2846
|
+
};
|
|
2847
|
+
|
|
2848
|
+
const create$5 = (id, method, params) => {
|
|
2849
|
+
const message = {
|
|
2850
|
+
id,
|
|
2851
|
+
jsonrpc: Two,
|
|
2852
|
+
method,
|
|
2853
|
+
params
|
|
2854
|
+
};
|
|
2855
|
+
return message;
|
|
2856
|
+
};
|
|
2857
|
+
|
|
2858
|
+
let id = 0;
|
|
2859
|
+
const create$4 = () => {
|
|
2860
|
+
return ++id;
|
|
2861
|
+
};
|
|
2862
|
+
|
|
2863
|
+
const registerPromise = map => {
|
|
2864
|
+
const id = create$4();
|
|
2865
|
+
const {
|
|
2866
|
+
promise,
|
|
2867
|
+
resolve
|
|
2868
|
+
} = Promise.withResolvers();
|
|
2869
|
+
map[id] = resolve;
|
|
2870
|
+
return {
|
|
2871
|
+
id,
|
|
2872
|
+
promise
|
|
2873
|
+
};
|
|
2874
|
+
};
|
|
2875
|
+
|
|
2876
|
+
const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => {
|
|
2877
|
+
const {
|
|
2878
|
+
id,
|
|
2879
|
+
promise
|
|
2880
|
+
} = registerPromise(callbacks);
|
|
2881
|
+
const message = create$5(id, method, params);
|
|
2882
|
+
if (useSendAndTransfer && ipc.sendAndTransfer) {
|
|
2883
|
+
ipc.sendAndTransfer(message);
|
|
2884
|
+
} else {
|
|
2885
|
+
ipc.send(message);
|
|
2886
|
+
}
|
|
2887
|
+
const responseMessage = await promise;
|
|
2888
|
+
return unwrapJsonRpcResult(responseMessage);
|
|
2889
|
+
};
|
|
2890
|
+
const createRpc = ipc => {
|
|
2891
|
+
const callbacks = Object.create(null);
|
|
2892
|
+
ipc._resolve = (id, response) => {
|
|
2893
|
+
const fn = callbacks[id];
|
|
2894
|
+
if (!fn) {
|
|
2895
|
+
console.warn(`callback ${id} may already be disposed`);
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
fn(response);
|
|
2899
|
+
delete callbacks[id];
|
|
2900
|
+
};
|
|
2901
|
+
const rpc = {
|
|
2902
|
+
async dispose() {
|
|
2903
|
+
await ipc?.dispose();
|
|
2904
|
+
},
|
|
2905
|
+
invoke(method, ...params) {
|
|
2906
|
+
return invokeHelper(callbacks, ipc, method, params, false);
|
|
2907
|
+
},
|
|
2908
|
+
invokeAndTransfer(method, ...params) {
|
|
2909
|
+
return invokeHelper(callbacks, ipc, method, params, true);
|
|
2910
|
+
},
|
|
2911
|
+
// @ts-ignore
|
|
2912
|
+
ipc,
|
|
2913
|
+
/**
|
|
2914
|
+
* @deprecated
|
|
2915
|
+
*/
|
|
2916
|
+
send(method, ...params) {
|
|
2917
|
+
const message = create$6(method, params);
|
|
2918
|
+
ipc.send(message);
|
|
2919
|
+
}
|
|
2920
|
+
};
|
|
2921
|
+
return rpc;
|
|
2922
|
+
};
|
|
2923
|
+
|
|
2924
|
+
const requiresSocket = () => {
|
|
2925
|
+
return false;
|
|
2926
|
+
};
|
|
2927
|
+
const preparePrettyError = error => {
|
|
2928
|
+
return error;
|
|
2929
|
+
};
|
|
2930
|
+
const logError = () => {
|
|
2931
|
+
// handled by renderer worker
|
|
2932
|
+
};
|
|
2933
|
+
const handleMessage = event => {
|
|
2934
|
+
const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
|
|
2935
|
+
const actualExecute = event?.target?.execute || execute;
|
|
2936
|
+
return handleJsonRpcMessage(event.target, event.data, actualExecute, event.target._resolve, preparePrettyError, logError, actualRequiresSocket);
|
|
2937
|
+
};
|
|
2938
|
+
|
|
2939
|
+
const handleIpc = ipc => {
|
|
2940
|
+
if ('addEventListener' in ipc) {
|
|
2941
|
+
ipc.addEventListener('message', handleMessage);
|
|
2942
|
+
} else if ('on' in ipc) {
|
|
2943
|
+
// deprecated
|
|
2944
|
+
ipc.on('message', handleMessage);
|
|
2945
|
+
}
|
|
2946
|
+
};
|
|
2947
|
+
|
|
2948
|
+
const listen$1 = async (module, options) => {
|
|
2949
|
+
const rawIpc = await module.listen(options);
|
|
2950
|
+
if (module.signal) {
|
|
2951
|
+
module.signal(rawIpc);
|
|
2952
|
+
}
|
|
2953
|
+
const ipc = module.wrap(rawIpc);
|
|
2954
|
+
return ipc;
|
|
2955
|
+
};
|
|
2956
|
+
|
|
2957
|
+
const create$3 = async ({
|
|
2958
|
+
commandMap,
|
|
2959
|
+
isMessagePortOpen = true,
|
|
2960
|
+
messagePort
|
|
2961
|
+
}) => {
|
|
2962
|
+
// TODO create a commandMap per rpc instance
|
|
2963
|
+
register$1(commandMap);
|
|
2964
|
+
const rawIpc = await IpcParentWithMessagePort$1.create({
|
|
2965
|
+
isMessagePortOpen,
|
|
2966
|
+
messagePort
|
|
2967
|
+
});
|
|
2968
|
+
const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
|
|
2969
|
+
handleIpc(ipc);
|
|
2970
|
+
const rpc = createRpc(ipc);
|
|
2971
|
+
messagePort.start();
|
|
2972
|
+
return rpc;
|
|
2973
|
+
};
|
|
2974
|
+
|
|
2975
|
+
const create$2 = async ({
|
|
2976
|
+
commandMap,
|
|
2977
|
+
isMessagePortOpen,
|
|
2978
|
+
send
|
|
2979
|
+
}) => {
|
|
2980
|
+
const {
|
|
2981
|
+
port1,
|
|
2982
|
+
port2
|
|
2983
|
+
} = new MessageChannel();
|
|
2984
|
+
await send(port1);
|
|
2985
|
+
return create$3({
|
|
2986
|
+
commandMap,
|
|
2987
|
+
isMessagePortOpen,
|
|
2988
|
+
messagePort: port2
|
|
2989
|
+
});
|
|
2990
|
+
};
|
|
2991
|
+
|
|
2992
|
+
const createSharedLazyRpc = factory => {
|
|
2993
|
+
let rpcPromise;
|
|
2994
|
+
const getOrCreate = () => {
|
|
2995
|
+
if (!rpcPromise) {
|
|
2996
|
+
rpcPromise = factory();
|
|
2997
|
+
}
|
|
2998
|
+
return rpcPromise;
|
|
2999
|
+
};
|
|
3000
|
+
return {
|
|
3001
|
+
async dispose() {
|
|
3002
|
+
const rpc = await getOrCreate();
|
|
3003
|
+
await rpc.dispose();
|
|
3004
|
+
},
|
|
3005
|
+
async invoke(method, ...params) {
|
|
3006
|
+
const rpc = await getOrCreate();
|
|
3007
|
+
return rpc.invoke(method, ...params);
|
|
3008
|
+
},
|
|
3009
|
+
async invokeAndTransfer(method, ...params) {
|
|
3010
|
+
const rpc = await getOrCreate();
|
|
3011
|
+
return rpc.invokeAndTransfer(method, ...params);
|
|
3012
|
+
},
|
|
3013
|
+
async send(method, ...params) {
|
|
3014
|
+
const rpc = await getOrCreate();
|
|
3015
|
+
rpc.send(method, ...params);
|
|
3016
|
+
}
|
|
3017
|
+
};
|
|
3018
|
+
};
|
|
3019
|
+
|
|
3020
|
+
const create$1 = async ({
|
|
3021
|
+
commandMap,
|
|
3022
|
+
isMessagePortOpen,
|
|
3023
|
+
send
|
|
3024
|
+
}) => {
|
|
3025
|
+
return createSharedLazyRpc(() => {
|
|
3026
|
+
return create$2({
|
|
3027
|
+
commandMap,
|
|
3028
|
+
isMessagePortOpen,
|
|
3029
|
+
send
|
|
3030
|
+
});
|
|
3031
|
+
});
|
|
3032
|
+
};
|
|
3033
|
+
|
|
3034
|
+
const create = async ({
|
|
3035
|
+
commandMap
|
|
3036
|
+
}) => {
|
|
3037
|
+
// TODO create a commandMap per rpc instance
|
|
3038
|
+
register$1(commandMap);
|
|
3039
|
+
const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
|
|
3040
|
+
handleIpc(ipc);
|
|
3041
|
+
const rpc = createRpc(ipc);
|
|
3042
|
+
return rpc;
|
|
3043
|
+
};
|
|
3044
|
+
|
|
3045
|
+
const commandMapRef = {};
|
|
3046
|
+
|
|
3047
|
+
const handleMessagePort = async port => {
|
|
3048
|
+
await create$3({
|
|
3049
|
+
commandMap: commandMapRef,
|
|
3050
|
+
isMessagePortOpen: true,
|
|
3051
|
+
messagePort: port
|
|
3052
|
+
});
|
|
3053
|
+
};
|
|
3054
|
+
|
|
3055
|
+
const initialize = async () => {
|
|
3056
|
+
// not needed anymore
|
|
3057
|
+
};
|
|
3058
|
+
|
|
3059
|
+
const getDefaultValue = id => {
|
|
3060
|
+
switch (id) {
|
|
3061
|
+
case EveryThing$1:
|
|
3062
|
+
return Command;
|
|
3063
|
+
default:
|
|
3064
|
+
return '';
|
|
3065
|
+
}
|
|
3066
|
+
};
|
|
3067
|
+
|
|
3068
|
+
const Commands = 'quickPick://commands';
|
|
3069
|
+
const EveryThing = 'quickPick://everything';
|
|
3070
|
+
const Recent = 'quickPick://recent';
|
|
3071
|
+
const ColorTheme = 'quickPick://color-theme';
|
|
3072
|
+
const Symbol$1 = 'quickPick://symbol';
|
|
3073
|
+
const View = 'quickPick://view';
|
|
3074
|
+
const Help = 'quickPick://help';
|
|
3075
|
+
const WorkspaceSymbol = 'quickPick://workspace-symbol';
|
|
3076
|
+
const Custom = 'quickPick://custom';
|
|
3077
|
+
const GoToLine = 'quickPick://go-to-line';
|
|
3078
|
+
|
|
3079
|
+
const getQuickPickProviderId = prefix => {
|
|
3080
|
+
switch (prefix) {
|
|
3081
|
+
case ColorTheme:
|
|
3082
|
+
return ColorTheme$1;
|
|
3083
|
+
case Commands:
|
|
3084
|
+
case EveryThing:
|
|
3085
|
+
case GoToLine:
|
|
3086
|
+
case Help:
|
|
3087
|
+
case Symbol$1:
|
|
3088
|
+
case View:
|
|
3089
|
+
case WorkspaceSymbol:
|
|
3090
|
+
return EveryThing$1;
|
|
3091
|
+
case Custom:
|
|
3092
|
+
return Custom$2;
|
|
3093
|
+
case Recent:
|
|
3094
|
+
return Recent$1;
|
|
3095
|
+
default:
|
|
3096
|
+
return File$2;
|
|
3097
|
+
}
|
|
3098
|
+
};
|
|
3099
|
+
|
|
3100
|
+
const parseArgs = (subId, args) => {
|
|
3101
|
+
if (subId !== Custom$2) {
|
|
3102
|
+
return {
|
|
3103
|
+
ignoreFocusOut: false,
|
|
3104
|
+
initialValue: ''
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
const last = args.at(-1);
|
|
3108
|
+
if (!last || typeof last !== 'object') {
|
|
3109
|
+
return {
|
|
3110
|
+
ignoreFocusOut: false,
|
|
3111
|
+
initialValue: ''
|
|
3112
|
+
};
|
|
3113
|
+
}
|
|
3114
|
+
return {
|
|
3115
|
+
// @ts-ignore
|
|
3116
|
+
ignoreFocusOut: Boolean(last.ignoreFocusOut),
|
|
3117
|
+
// @ts-ignore
|
|
3118
|
+
initialValue: String(last.initialValue)
|
|
3119
|
+
};
|
|
3120
|
+
};
|
|
3121
|
+
const loadContent = async state => {
|
|
3122
|
+
const {
|
|
3123
|
+
args,
|
|
3124
|
+
assetDir,
|
|
3125
|
+
fileIconCache,
|
|
3126
|
+
height,
|
|
3127
|
+
itemHeight,
|
|
3128
|
+
maxVisibleItems,
|
|
3129
|
+
platform,
|
|
3130
|
+
uri
|
|
3131
|
+
} = state;
|
|
3132
|
+
const id = getQuickPickProviderId(uri);
|
|
3133
|
+
const value = getDefaultValue(id);
|
|
3134
|
+
const prefix = getQuickPickPrefix(value);
|
|
3135
|
+
const subId = getQuickPickSubProviderId(id, prefix);
|
|
3136
|
+
const newPicks = await getPicks(subId, value, args, {
|
|
3137
|
+
assetDir,
|
|
3138
|
+
platform
|
|
3139
|
+
});
|
|
3140
|
+
array(newPicks);
|
|
3141
|
+
const filterValue = getFilterValue(id, subId, value);
|
|
3142
|
+
const items = filterQuickPickItems(newPicks, filterValue);
|
|
3143
|
+
const minLineY = 0;
|
|
3144
|
+
const maxLineY = Math.min(minLineY + maxVisibleItems, newPicks.length);
|
|
3145
|
+
const sliced = newPicks.slice(minLineY, maxLineY);
|
|
3146
|
+
const {
|
|
3147
|
+
icons,
|
|
3148
|
+
newFileIconCache
|
|
3149
|
+
} = await getQuickPickFileIcons(sliced, fileIconCache);
|
|
3150
|
+
const listHeight = getListHeight(items.length, itemHeight, height);
|
|
3151
|
+
const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, items.length);
|
|
3152
|
+
const parsedArgs = parseArgs(subId, args);
|
|
3153
|
+
const finalValue = parsedArgs.initialValue || value;
|
|
3154
|
+
return {
|
|
3155
|
+
...state,
|
|
3156
|
+
args,
|
|
3157
|
+
cursorOffset: value.length,
|
|
3158
|
+
fileIconCache: newFileIconCache,
|
|
3159
|
+
finalDeltaY,
|
|
3160
|
+
focused: true,
|
|
3161
|
+
focusedIndex: 0,
|
|
3162
|
+
icons,
|
|
3163
|
+
inputSource: Script,
|
|
3164
|
+
items,
|
|
3165
|
+
maxLineY,
|
|
3166
|
+
minLineY,
|
|
3167
|
+
picks: newPicks,
|
|
3168
|
+
placeholder: '',
|
|
3169
|
+
providerId: id,
|
|
3170
|
+
state: Finished,
|
|
3171
|
+
value: finalValue
|
|
3172
|
+
};
|
|
3173
|
+
};
|
|
3174
|
+
|
|
3175
|
+
const callbacks = Object.create(null);
|
|
3176
|
+
const executeCallback = id => {
|
|
3177
|
+
const fn = callbacks[id];
|
|
3178
|
+
delete callbacks[id];
|
|
3179
|
+
fn();
|
|
3180
|
+
};
|
|
3181
|
+
|
|
3182
|
+
const getVisible$1 = (items, minLineY, maxLineY, icons) => {
|
|
3183
|
+
const range = items.slice(minLineY, maxLineY);
|
|
3184
|
+
const protoVisibleItems = range.map((item, index) => {
|
|
3185
|
+
return {
|
|
3186
|
+
...item,
|
|
3187
|
+
fileIcon: icons[index]
|
|
3188
|
+
};
|
|
3189
|
+
});
|
|
3190
|
+
return protoVisibleItems;
|
|
3191
|
+
};
|
|
3192
|
+
|
|
3193
|
+
const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
|
|
3194
|
+
if (size >= contentSize) {
|
|
3195
|
+
return 0;
|
|
3196
|
+
}
|
|
3197
|
+
return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
|
|
3198
|
+
};
|
|
3199
|
+
|
|
3200
|
+
const emptyHighlightSections = [];
|
|
3201
|
+
|
|
3202
|
+
const getHighlightSections = (highlights, label) => {
|
|
3203
|
+
if (highlights.length === 0) {
|
|
3204
|
+
return emptyHighlightSections;
|
|
3205
|
+
}
|
|
3206
|
+
const sections = [];
|
|
3207
|
+
let position = 0;
|
|
3208
|
+
for (let i = 0; i < highlights.length; i += 2) {
|
|
3209
|
+
const highlightStart = highlights[i];
|
|
3210
|
+
const highlightEnd = highlights[i + 1];
|
|
3211
|
+
if (position < highlightStart) {
|
|
3212
|
+
const beforeText = label.slice(position, highlightStart);
|
|
3213
|
+
sections.push({
|
|
3214
|
+
highlighted: false,
|
|
3215
|
+
text: beforeText
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3218
|
+
const highlightText = label.slice(highlightStart, highlightEnd);
|
|
3219
|
+
sections.push({
|
|
3220
|
+
highlighted: true,
|
|
3221
|
+
text: highlightText
|
|
3222
|
+
});
|
|
3223
|
+
position = highlightEnd;
|
|
3224
|
+
}
|
|
3225
|
+
if (position < label.length) {
|
|
3226
|
+
const afterText = label.slice(position);
|
|
3227
|
+
sections.push({
|
|
3228
|
+
highlighted: false,
|
|
3229
|
+
text: afterText
|
|
3230
|
+
});
|
|
3231
|
+
}
|
|
3232
|
+
return sections;
|
|
3233
|
+
};
|
|
3234
|
+
|
|
3235
|
+
const getVisible = (setSize, protoVisibleItems, minLineY, focusedIndex) => {
|
|
3236
|
+
const visibleItems = protoVisibleItems.map((visibleItem, i) => {
|
|
3237
|
+
const highlights = visibleItem.matches.slice(1);
|
|
3238
|
+
const sections = getHighlightSections(highlights, visibleItem.label);
|
|
3239
|
+
return {
|
|
3240
|
+
...visibleItem,
|
|
3241
|
+
highlights: sections,
|
|
3242
|
+
isActive: i === focusedIndex,
|
|
3243
|
+
posInSet: minLineY + i + 1,
|
|
3244
|
+
setSize
|
|
3245
|
+
};
|
|
3246
|
+
});
|
|
3247
|
+
return visibleItems;
|
|
3248
|
+
};
|
|
3249
|
+
|
|
3250
|
+
const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
|
|
3251
|
+
const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
|
|
3252
|
+
return scrollBarOffset;
|
|
3253
|
+
};
|
|
3254
|
+
const getScrollBarY = getScrollBarOffset;
|
|
3255
|
+
|
|
3256
|
+
const createQuickPickViewModel = (oldState, newState) => {
|
|
3257
|
+
const {
|
|
3258
|
+
cursorOffset,
|
|
3259
|
+
deltaY,
|
|
3260
|
+
finalDeltaY,
|
|
3261
|
+
focused,
|
|
3262
|
+
focusedIndex,
|
|
3263
|
+
headerHeight,
|
|
3264
|
+
height,
|
|
3265
|
+
icons,
|
|
3266
|
+
itemHeight,
|
|
3267
|
+
items,
|
|
3268
|
+
maxLineY,
|
|
3269
|
+
minimumSliderSize,
|
|
3270
|
+
minLineY,
|
|
3271
|
+
uid,
|
|
3272
|
+
value
|
|
3273
|
+
} = newState;
|
|
3274
|
+
const protoVisibleItems = getVisible$1(items, minLineY, maxLineY, icons);
|
|
3275
|
+
const visibleItems = getVisible(items.length, protoVisibleItems, minLineY, focusedIndex);
|
|
3276
|
+
const oldFocusedIndex = oldState.focusedIndex - oldState.minLineY;
|
|
3277
|
+
const newFocusedIndex = focusedIndex - minLineY;
|
|
3278
|
+
const itemCount = items.length;
|
|
3279
|
+
const listHeight = getListHeight(itemCount, itemHeight, height);
|
|
3280
|
+
const contentHeight = itemCount * itemHeight;
|
|
3281
|
+
const scrollBarHeight = getScrollBarSize(listHeight, contentHeight, minimumSliderSize);
|
|
3282
|
+
const scrollBarY = getScrollBarY(deltaY, finalDeltaY, height - headerHeight, scrollBarHeight);
|
|
3283
|
+
const roundedScrollBarY = Math.round(scrollBarY);
|
|
3284
|
+
return {
|
|
3285
|
+
cursorOffset,
|
|
3286
|
+
focused,
|
|
3287
|
+
height,
|
|
3288
|
+
newFocusedIndex,
|
|
3289
|
+
oldFocusedIndex,
|
|
3290
|
+
scrollBarHeight,
|
|
3291
|
+
scrollBarTop: roundedScrollBarY,
|
|
3292
|
+
uid,
|
|
3293
|
+
value,
|
|
3294
|
+
visibleItems
|
|
3295
|
+
};
|
|
3296
|
+
};
|
|
3297
|
+
|
|
3298
|
+
const SetCursorOffset = 'setCursorOffset';
|
|
3299
|
+
const SetFocusedIndex = 'setFocusedIndex';
|
|
3300
|
+
const SetItemsHeight = 'setItemsHeight';
|
|
3301
|
+
|
|
3302
|
+
const renderCursorOffset = newState => {
|
|
3303
|
+
return ['Viewlet.send', newState.uid, /* method */SetCursorOffset, /* cursorOffset */newState.cursorOffset];
|
|
3304
|
+
};
|
|
3305
|
+
|
|
3306
|
+
const QuickPickInput = 'QuickPickInput';
|
|
3307
|
+
|
|
3308
|
+
const renderFocus = newState => {
|
|
3309
|
+
return ['Viewlet.focusElementByName', QuickPickInput];
|
|
3310
|
+
};
|
|
3311
|
+
|
|
3312
|
+
const renderFocusedIndex = newState => {
|
|
3313
|
+
return ['Viewlet.send', newState.uid, /* method */SetFocusedIndex, /* oldFocusedIndex */newState.oldFocusedIndex, /* newFocusedIndex */newState.newFocusedIndex];
|
|
3314
|
+
};
|
|
3315
|
+
|
|
3316
|
+
const renderHeight = newState => {
|
|
3317
|
+
const {
|
|
3318
|
+
height,
|
|
3319
|
+
uid
|
|
3320
|
+
} = newState;
|
|
3321
|
+
if (height === 0) {
|
|
3322
|
+
return ['Viewlet.send', uid, /* method */SetItemsHeight, /* height */20];
|
|
3323
|
+
}
|
|
3324
|
+
return ['Viewlet.send', uid, /* method */SetItemsHeight, /* height */height];
|
|
3325
|
+
};
|
|
3326
|
+
|
|
3327
|
+
const Div = 4;
|
|
3328
|
+
const Input = 6;
|
|
3329
|
+
const Span = 8;
|
|
3330
|
+
const Text = 12;
|
|
3331
|
+
const Img = 17;
|
|
3332
|
+
const Reference = 100;
|
|
3333
|
+
|
|
3334
|
+
const mergeClassNames = (...classNames) => {
|
|
3335
|
+
return classNames.filter(Boolean).join(' ');
|
|
3336
|
+
};
|
|
3337
|
+
|
|
3338
|
+
const px = value => {
|
|
3339
|
+
return `${value}px`;
|
|
3340
|
+
};
|
|
3341
|
+
const position = (x, y) => {
|
|
3342
|
+
return `${x}px ${y}px`;
|
|
3343
|
+
};
|
|
3344
|
+
|
|
3345
|
+
const text = data => {
|
|
3346
|
+
return {
|
|
3347
|
+
childCount: 0,
|
|
3348
|
+
text: data,
|
|
3349
|
+
type: Text
|
|
3350
|
+
};
|
|
3351
|
+
};
|
|
3352
|
+
|
|
3353
|
+
const SetText = 1;
|
|
3354
|
+
const Replace = 2;
|
|
3355
|
+
const SetAttribute = 3;
|
|
3356
|
+
const RemoveAttribute = 4;
|
|
3357
|
+
const Add = 6;
|
|
3358
|
+
const NavigateChild = 7;
|
|
3359
|
+
const NavigateParent = 8;
|
|
3360
|
+
const RemoveChild = 9;
|
|
3361
|
+
const NavigateSibling = 10;
|
|
3362
|
+
const SetReferenceNodeUid = 11;
|
|
3363
|
+
|
|
3364
|
+
const isKey = key => {
|
|
3365
|
+
return key !== 'type' && key !== 'childCount';
|
|
3366
|
+
};
|
|
3367
|
+
|
|
3368
|
+
const getKeys = node => {
|
|
3369
|
+
const keys = Object.keys(node).filter(isKey);
|
|
3370
|
+
return keys;
|
|
3371
|
+
};
|
|
3372
|
+
|
|
3373
|
+
const arrayToTree = nodes => {
|
|
3374
|
+
const result = [];
|
|
3375
|
+
let i = 0;
|
|
3376
|
+
while (i < nodes.length) {
|
|
3377
|
+
const node = nodes[i];
|
|
3378
|
+
const {
|
|
3379
|
+
children,
|
|
3380
|
+
nodesConsumed
|
|
3381
|
+
} = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
|
|
3382
|
+
result.push({
|
|
3383
|
+
node,
|
|
3384
|
+
children
|
|
3385
|
+
});
|
|
3386
|
+
i += 1 + nodesConsumed;
|
|
3387
|
+
}
|
|
3388
|
+
return result;
|
|
3389
|
+
};
|
|
3390
|
+
const getChildrenWithCount = (nodes, startIndex, childCount) => {
|
|
3391
|
+
if (childCount === 0) {
|
|
3392
|
+
return {
|
|
3393
|
+
children: [],
|
|
3394
|
+
nodesConsumed: 0
|
|
3395
|
+
};
|
|
3396
|
+
}
|
|
3397
|
+
const children = [];
|
|
3398
|
+
let i = startIndex;
|
|
3399
|
+
let remaining = childCount;
|
|
3400
|
+
let totalConsumed = 0;
|
|
3401
|
+
while (remaining > 0 && i < nodes.length) {
|
|
3402
|
+
const node = nodes[i];
|
|
3403
|
+
const nodeChildCount = node.childCount || 0;
|
|
3404
|
+
const {
|
|
3405
|
+
children: nodeChildren,
|
|
3406
|
+
nodesConsumed
|
|
3407
|
+
} = getChildrenWithCount(nodes, i + 1, nodeChildCount);
|
|
3408
|
+
children.push({
|
|
3409
|
+
node,
|
|
3410
|
+
children: nodeChildren
|
|
3411
|
+
});
|
|
3412
|
+
const nodeSize = 1 + nodesConsumed;
|
|
3413
|
+
i += nodeSize;
|
|
3414
|
+
totalConsumed += nodeSize;
|
|
3415
|
+
remaining--;
|
|
3416
|
+
}
|
|
3417
|
+
return {
|
|
3418
|
+
children,
|
|
3419
|
+
nodesConsumed: totalConsumed
|
|
3420
|
+
};
|
|
3421
|
+
};
|
|
3422
|
+
|
|
3423
|
+
const compareNodes = (oldNode, newNode) => {
|
|
3424
|
+
const patches = [];
|
|
3425
|
+
// Check if node type changed - return null to signal incompatible nodes
|
|
3426
|
+
// (caller should handle this with a Replace operation)
|
|
3427
|
+
if (oldNode.type !== newNode.type) {
|
|
3428
|
+
return null;
|
|
3429
|
+
}
|
|
3430
|
+
// Handle reference nodes - special handling for uid changes
|
|
3431
|
+
if (oldNode.type === Reference) {
|
|
3432
|
+
if (oldNode.uid !== newNode.uid) {
|
|
3433
|
+
patches.push({
|
|
3434
|
+
type: SetReferenceNodeUid,
|
|
3435
|
+
uid: newNode.uid
|
|
3436
|
+
});
|
|
3437
|
+
}
|
|
3438
|
+
return patches;
|
|
3439
|
+
}
|
|
3440
|
+
// Handle text nodes
|
|
3441
|
+
if (oldNode.type === Text && newNode.type === Text) {
|
|
3442
|
+
if (oldNode.text !== newNode.text) {
|
|
3443
|
+
patches.push({
|
|
3444
|
+
type: SetText,
|
|
3445
|
+
value: newNode.text
|
|
3446
|
+
});
|
|
3447
|
+
}
|
|
3448
|
+
return patches;
|
|
3449
|
+
}
|
|
3450
|
+
// Compare attributes
|
|
3451
|
+
const oldKeys = getKeys(oldNode);
|
|
3452
|
+
const newKeys = getKeys(newNode);
|
|
3453
|
+
// Check for attribute changes
|
|
3454
|
+
for (const key of newKeys) {
|
|
3455
|
+
if (oldNode[key] !== newNode[key]) {
|
|
3456
|
+
patches.push({
|
|
3457
|
+
type: SetAttribute,
|
|
3458
|
+
key,
|
|
3459
|
+
value: newNode[key]
|
|
3460
|
+
});
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
// Check for removed attributes
|
|
3464
|
+
for (const key of oldKeys) {
|
|
3465
|
+
if (!(key in newNode)) {
|
|
3466
|
+
patches.push({
|
|
3467
|
+
type: RemoveAttribute,
|
|
3468
|
+
key
|
|
3469
|
+
});
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
return patches;
|
|
3473
|
+
};
|
|
3474
|
+
|
|
3475
|
+
const treeToArray = node => {
|
|
3476
|
+
const result = [node.node];
|
|
3477
|
+
for (const child of node.children) {
|
|
3478
|
+
result.push(...treeToArray(child));
|
|
3479
|
+
}
|
|
3480
|
+
return result;
|
|
3481
|
+
};
|
|
3482
|
+
|
|
3483
|
+
const diffChildren = (oldChildren, newChildren, patches) => {
|
|
3484
|
+
const maxLength = Math.max(oldChildren.length, newChildren.length);
|
|
3485
|
+
// Track where we are: -1 means at parent, >= 0 means at child index
|
|
3486
|
+
let currentChildIndex = -1;
|
|
3487
|
+
// Collect indices of children to remove (we'll add these patches at the end in reverse order)
|
|
3488
|
+
const indicesToRemove = [];
|
|
3489
|
+
for (let i = 0; i < maxLength; i++) {
|
|
3490
|
+
const oldNode = oldChildren[i];
|
|
3491
|
+
const newNode = newChildren[i];
|
|
3492
|
+
if (!oldNode && !newNode) {
|
|
3493
|
+
continue;
|
|
3494
|
+
}
|
|
3495
|
+
if (!oldNode) {
|
|
3496
|
+
// Add new node - we should be at the parent
|
|
3497
|
+
if (currentChildIndex >= 0) {
|
|
3498
|
+
// Navigate back to parent
|
|
3499
|
+
patches.push({
|
|
3500
|
+
type: NavigateParent
|
|
3501
|
+
});
|
|
3502
|
+
currentChildIndex = -1;
|
|
3503
|
+
}
|
|
3504
|
+
// Flatten the entire subtree so renderInternal can handle it
|
|
3505
|
+
const flatNodes = treeToArray(newNode);
|
|
3506
|
+
patches.push({
|
|
3507
|
+
type: Add,
|
|
3508
|
+
nodes: flatNodes
|
|
3509
|
+
});
|
|
3510
|
+
} else if (newNode) {
|
|
3511
|
+
// Compare nodes to see if we need any patches
|
|
3512
|
+
const nodePatches = compareNodes(oldNode.node, newNode.node);
|
|
3513
|
+
// If nodePatches is null, the node types are incompatible - need to replace
|
|
3514
|
+
if (nodePatches === null) {
|
|
3515
|
+
// Navigate to this child
|
|
3516
|
+
if (currentChildIndex === -1) {
|
|
3517
|
+
patches.push({
|
|
3518
|
+
type: NavigateChild,
|
|
3519
|
+
index: i
|
|
3520
|
+
});
|
|
3521
|
+
currentChildIndex = i;
|
|
3522
|
+
} else if (currentChildIndex !== i) {
|
|
3523
|
+
patches.push({
|
|
3524
|
+
type: NavigateSibling,
|
|
3525
|
+
index: i
|
|
3526
|
+
});
|
|
3527
|
+
currentChildIndex = i;
|
|
3528
|
+
}
|
|
3529
|
+
// Replace the entire subtree
|
|
3530
|
+
const flatNodes = treeToArray(newNode);
|
|
3531
|
+
patches.push({
|
|
3532
|
+
type: Replace,
|
|
3533
|
+
nodes: flatNodes
|
|
3534
|
+
});
|
|
3535
|
+
// After replace, we're at the new element (same position)
|
|
3536
|
+
continue;
|
|
3537
|
+
}
|
|
3538
|
+
// Check if we need to recurse into children
|
|
3539
|
+
const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
|
|
3540
|
+
// Only navigate to this element if we need to do something
|
|
3541
|
+
if (nodePatches.length > 0 || hasChildrenToCompare) {
|
|
3542
|
+
// Navigate to this child if not already there
|
|
3543
|
+
if (currentChildIndex === -1) {
|
|
3544
|
+
patches.push({
|
|
3545
|
+
type: NavigateChild,
|
|
3546
|
+
index: i
|
|
3547
|
+
});
|
|
3548
|
+
currentChildIndex = i;
|
|
3549
|
+
} else if (currentChildIndex !== i) {
|
|
3550
|
+
patches.push({
|
|
3551
|
+
type: NavigateSibling,
|
|
3552
|
+
index: i
|
|
3553
|
+
});
|
|
3554
|
+
currentChildIndex = i;
|
|
3555
|
+
}
|
|
3556
|
+
// Apply node patches (these apply to the current element, not children)
|
|
3557
|
+
if (nodePatches.length > 0) {
|
|
3558
|
+
patches.push(...nodePatches);
|
|
3559
|
+
}
|
|
3560
|
+
// Compare children recursively
|
|
3561
|
+
if (hasChildrenToCompare) {
|
|
3562
|
+
diffChildren(oldNode.children, newNode.children, patches);
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
} else {
|
|
3566
|
+
// Remove old node - collect the index for later removal
|
|
3567
|
+
indicesToRemove.push(i);
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
// Navigate back to parent if we ended at a child
|
|
3571
|
+
if (currentChildIndex >= 0) {
|
|
3572
|
+
patches.push({
|
|
3573
|
+
type: NavigateParent
|
|
3574
|
+
});
|
|
3575
|
+
currentChildIndex = -1;
|
|
3576
|
+
}
|
|
3577
|
+
// Add remove patches in reverse order (highest index first)
|
|
3578
|
+
// This ensures indices remain valid as we remove
|
|
3579
|
+
for (let j = indicesToRemove.length - 1; j >= 0; j--) {
|
|
3580
|
+
patches.push({
|
|
3581
|
+
type: RemoveChild,
|
|
3582
|
+
index: indicesToRemove[j]
|
|
3583
|
+
});
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
const diffTrees = (oldTree, newTree, patches, path) => {
|
|
3587
|
+
// At the root level (path.length === 0), we're already AT the element
|
|
3588
|
+
// So we compare the root node directly, then compare its children
|
|
3589
|
+
if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
|
|
3590
|
+
const oldNode = oldTree[0];
|
|
3591
|
+
const newNode = newTree[0];
|
|
3592
|
+
// Compare root nodes
|
|
3593
|
+
const nodePatches = compareNodes(oldNode.node, newNode.node);
|
|
3594
|
+
// If nodePatches is null, the root node types are incompatible - need to replace
|
|
3595
|
+
if (nodePatches === null) {
|
|
3596
|
+
const flatNodes = treeToArray(newNode);
|
|
3597
|
+
patches.push({
|
|
3598
|
+
type: Replace,
|
|
3599
|
+
nodes: flatNodes
|
|
3600
|
+
});
|
|
3601
|
+
return;
|
|
3602
|
+
}
|
|
3603
|
+
if (nodePatches.length > 0) {
|
|
3604
|
+
patches.push(...nodePatches);
|
|
3605
|
+
}
|
|
3606
|
+
// Compare children
|
|
3607
|
+
if (oldNode.children.length > 0 || newNode.children.length > 0) {
|
|
3608
|
+
diffChildren(oldNode.children, newNode.children, patches);
|
|
3609
|
+
}
|
|
3610
|
+
} else {
|
|
3611
|
+
// Non-root level or multiple root elements - use the regular comparison
|
|
3612
|
+
diffChildren(oldTree, newTree, patches);
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3615
|
+
|
|
3616
|
+
const removeTrailingNavigationPatches = patches => {
|
|
3617
|
+
// Find the last non-navigation patch
|
|
3618
|
+
let lastNonNavigationIndex = -1;
|
|
3619
|
+
for (let i = patches.length - 1; i >= 0; i--) {
|
|
3620
|
+
const patch = patches[i];
|
|
3621
|
+
if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
|
|
3622
|
+
lastNonNavigationIndex = i;
|
|
3623
|
+
break;
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
// Return patches up to and including the last non-navigation patch
|
|
3627
|
+
return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
|
|
3628
|
+
};
|
|
3629
|
+
|
|
3630
|
+
const diffTree = (oldNodes, newNodes) => {
|
|
3631
|
+
// Step 1: Convert flat arrays to tree structures
|
|
3632
|
+
const oldTree = arrayToTree(oldNodes);
|
|
3633
|
+
const newTree = arrayToTree(newNodes);
|
|
3634
|
+
// Step 3: Compare the trees
|
|
3635
|
+
const patches = [];
|
|
3636
|
+
diffTrees(oldTree, newTree, patches, []);
|
|
3637
|
+
// Remove trailing navigation patches since they serve no purpose
|
|
3638
|
+
return removeTrailingNavigationPatches(patches);
|
|
3639
|
+
};
|
|
3640
|
+
|
|
3641
|
+
const ComboBox = 'combobox';
|
|
3642
|
+
const ListBox = 'listbox';
|
|
3643
|
+
const None = 'none';
|
|
3644
|
+
const Option = 'option';
|
|
3645
|
+
|
|
3646
|
+
const ContainContent = 'ContainContent';
|
|
3647
|
+
const FileIcon = 'FileIcon';
|
|
3648
|
+
const InputBox = 'InputBox';
|
|
3649
|
+
const Label = 'Label';
|
|
3650
|
+
const List = 'List';
|
|
3651
|
+
const ListItems = 'ListItems';
|
|
3652
|
+
const MaskIcon = 'MaskIcon';
|
|
3653
|
+
const QuickPick$1 = 'QuickPick';
|
|
3654
|
+
const QuickPickHeader = 'QuickPickHeader';
|
|
3655
|
+
const QuickPickHighlight = 'QuickPickHighlight';
|
|
3656
|
+
const QuickPickItem = 'QuickPickItem';
|
|
3657
|
+
const QuickPickItemActive$1 = 'QuickPickItemActive';
|
|
3658
|
+
const QuickPickItemDescription = 'QuickPickItemDescription';
|
|
3659
|
+
const QuickPickItemLabel = 'QuickPickItemLabel';
|
|
3660
|
+
const QuickPickMaskIcon = 'QuickPickMaskIcon';
|
|
3661
|
+
const QuickPickStatus = 'QuickPickStatus';
|
|
3662
|
+
const ScrollBar = 'ScrollBar';
|
|
3663
|
+
const ScrollBarSmall = 'ScrollBarSmall';
|
|
3664
|
+
const ScrollBarThumb = 'ScrollBarThumb';
|
|
3665
|
+
const Viewlet = 'Viewlet';
|
|
3666
|
+
|
|
3667
|
+
const HandleWheel = 'handleWheel';
|
|
3668
|
+
const HandlePointerDown = 'handlePointerDown';
|
|
3669
|
+
const HandleBeforeInput = 'handleBeforeInput';
|
|
3670
|
+
const HandleBlur = 'handleBlur';
|
|
3671
|
+
const HandleFocus = 'handleFocus';
|
|
3672
|
+
const HandleInput = 'handleInput';
|
|
3673
|
+
|
|
3674
|
+
const QuickPick = 'QuickPick';
|
|
3675
|
+
const QuickPickItems = 'QuickPickItems';
|
|
3676
|
+
const QuickPickItemActive = 'QuickPickItemActive';
|
|
3677
|
+
|
|
3678
|
+
const getQuickPickInputVirtualDom = () => {
|
|
3679
|
+
const ariaLabel = typeNameofCommandToRun();
|
|
3680
|
+
return {
|
|
3681
|
+
ariaAutoComplete: 'list',
|
|
3682
|
+
ariaExpanded: true,
|
|
3683
|
+
ariaLabel: ariaLabel,
|
|
3684
|
+
autocapitalize: 'off',
|
|
3685
|
+
autocomplete: 'off',
|
|
3686
|
+
childCount: 0,
|
|
3687
|
+
className: InputBox,
|
|
3688
|
+
inputType: 'text',
|
|
3689
|
+
name: QuickPickInput,
|
|
3690
|
+
onBeforeInput: HandleBeforeInput,
|
|
3691
|
+
onBlur: HandleBlur,
|
|
3692
|
+
onFocus: HandleFocus,
|
|
3693
|
+
onInput: HandleInput,
|
|
3694
|
+
role: ComboBox,
|
|
3695
|
+
spellcheck: false,
|
|
3696
|
+
type: Input
|
|
3697
|
+
};
|
|
3698
|
+
};
|
|
3699
|
+
|
|
3700
|
+
const getQuickPickHeaderVirtualDom = () => {
|
|
3701
|
+
return [{
|
|
3702
|
+
childCount: 1,
|
|
3703
|
+
className: QuickPickHeader,
|
|
3704
|
+
type: Div
|
|
3705
|
+
}, getQuickPickInputVirtualDom()];
|
|
3706
|
+
};
|
|
3707
|
+
|
|
3708
|
+
const getFileIconVirtualDom = icon => {
|
|
3709
|
+
return {
|
|
3710
|
+
childCount: 0,
|
|
3711
|
+
className: FileIcon,
|
|
3712
|
+
role: None,
|
|
3713
|
+
src: icon,
|
|
3714
|
+
type: Img
|
|
3715
|
+
};
|
|
3716
|
+
};
|
|
3717
|
+
|
|
3718
|
+
const quickPickHighlight = {
|
|
3719
|
+
childCount: 1,
|
|
3720
|
+
className: QuickPickHighlight,
|
|
3721
|
+
type: Span
|
|
3722
|
+
};
|
|
3723
|
+
const getHighlights = (sections, label) => {
|
|
3724
|
+
const labelDom = {
|
|
3725
|
+
childCount: 0,
|
|
3726
|
+
className: QuickPickItemLabel,
|
|
3727
|
+
type: Div
|
|
3728
|
+
};
|
|
3729
|
+
const nodes = [labelDom];
|
|
3730
|
+
if (sections.length === 0) {
|
|
3731
|
+
labelDom.childCount++;
|
|
3732
|
+
nodes.push(text(label));
|
|
3733
|
+
} else {
|
|
3734
|
+
for (const section of sections) {
|
|
3735
|
+
if (section.highlighted) {
|
|
3736
|
+
labelDom.childCount++;
|
|
3737
|
+
nodes.push(quickPickHighlight, text(section.text));
|
|
3738
|
+
} else {
|
|
3739
|
+
labelDom.childCount++;
|
|
3740
|
+
nodes.push(text(section.text));
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
return nodes;
|
|
3745
|
+
};
|
|
3746
|
+
|
|
3747
|
+
const getQuickPickItemVirtualDom = visibleItem => {
|
|
3748
|
+
const {
|
|
3749
|
+
description,
|
|
3750
|
+
fileIcon,
|
|
3751
|
+
highlights,
|
|
3752
|
+
icon,
|
|
3753
|
+
isActive,
|
|
3754
|
+
label,
|
|
3755
|
+
posInSet,
|
|
3756
|
+
setSize
|
|
3757
|
+
} = visibleItem;
|
|
3758
|
+
const dom = [{
|
|
3759
|
+
ariaPosInSet: posInSet,
|
|
3760
|
+
ariaSetSize: setSize,
|
|
3761
|
+
childCount: 1,
|
|
3762
|
+
className: QuickPickItem,
|
|
3763
|
+
role: Option,
|
|
3764
|
+
type: Div
|
|
3765
|
+
}];
|
|
3766
|
+
const parent = dom[0];
|
|
3767
|
+
if (isActive) {
|
|
3768
|
+
parent.id = QuickPickItemActive;
|
|
3769
|
+
parent.className += ' ' + QuickPickItemActive$1;
|
|
3770
|
+
}
|
|
3771
|
+
if (fileIcon) {
|
|
3772
|
+
parent.childCount++;
|
|
3773
|
+
dom.push(getFileIconVirtualDom(fileIcon));
|
|
3774
|
+
} else if (icon) {
|
|
3775
|
+
parent.childCount++;
|
|
3776
|
+
dom.push({
|
|
3777
|
+
childCount: 0,
|
|
3778
|
+
className: mergeClassNames(QuickPickMaskIcon, MaskIcon, `MaskIcon${icon}`),
|
|
3779
|
+
type: Div
|
|
3780
|
+
});
|
|
3781
|
+
}
|
|
3782
|
+
const highlightDom = getHighlights(highlights, label);
|
|
3783
|
+
dom.push(...highlightDom);
|
|
3784
|
+
if (description) {
|
|
3785
|
+
parent.childCount++;
|
|
3786
|
+
dom.push({
|
|
3787
|
+
childCount: 1,
|
|
3788
|
+
className: QuickPickItemDescription,
|
|
3789
|
+
type: Div
|
|
3790
|
+
}, text(description));
|
|
3791
|
+
}
|
|
3792
|
+
return dom;
|
|
3793
|
+
};
|
|
3794
|
+
|
|
3795
|
+
const getQuickPickNoResultsVirtualDom = () => {
|
|
3796
|
+
const noResults$1 = noResults();
|
|
3797
|
+
return [{
|
|
3798
|
+
childCount: 1,
|
|
3799
|
+
className: mergeClassNames(QuickPickItem, QuickPickItemActive$1, QuickPickStatus),
|
|
3800
|
+
type: Div
|
|
3801
|
+
}, {
|
|
3802
|
+
childCount: 1,
|
|
3803
|
+
className: Label,
|
|
3804
|
+
type: Div
|
|
3805
|
+
}, text(noResults$1)];
|
|
3806
|
+
};
|
|
3807
|
+
|
|
3808
|
+
const getQuickPickItemsVirtualDom = visibleItems => {
|
|
3809
|
+
if (visibleItems.length === 0) {
|
|
3810
|
+
return getQuickPickNoResultsVirtualDom();
|
|
3811
|
+
}
|
|
3812
|
+
const dom = visibleItems.flatMap(getQuickPickItemVirtualDom);
|
|
3813
|
+
return dom;
|
|
3814
|
+
};
|
|
3815
|
+
|
|
3816
|
+
const getScrollBarVirtualDom = (scrollBarHeight, scrollBarTop) => {
|
|
3817
|
+
const shouldShowScrollbar = scrollBarHeight > 0;
|
|
3818
|
+
if (!shouldShowScrollbar) {
|
|
3819
|
+
return [];
|
|
3820
|
+
}
|
|
3821
|
+
const heightString = px(scrollBarHeight);
|
|
3822
|
+
const translateString = position(0, scrollBarTop);
|
|
3823
|
+
return [{
|
|
3824
|
+
childCount: 1,
|
|
3825
|
+
className: mergeClassNames(ScrollBar, ScrollBarSmall),
|
|
3826
|
+
type: Div
|
|
3827
|
+
}, {
|
|
3828
|
+
childCount: 0,
|
|
3829
|
+
className: ScrollBarThumb,
|
|
3830
|
+
height: heightString,
|
|
3831
|
+
translate: translateString,
|
|
3832
|
+
type: Div
|
|
3833
|
+
}];
|
|
3834
|
+
};
|
|
3835
|
+
|
|
3836
|
+
const getQuickPickVirtualDom = (visibleItems, scrollBarHeight, scrollBarTop) => {
|
|
3837
|
+
const quickOpen$1 = quickOpen();
|
|
3838
|
+
const shouldShowScrollbar = scrollBarHeight > 0;
|
|
3839
|
+
return [{
|
|
3840
|
+
ariaLabel: quickOpen$1,
|
|
3841
|
+
childCount: 2,
|
|
3842
|
+
className: mergeClassNames(Viewlet, QuickPick$1),
|
|
3843
|
+
id: QuickPick,
|
|
3844
|
+
type: Div
|
|
3845
|
+
}, ...getQuickPickHeaderVirtualDom(), {
|
|
3846
|
+
ariaActivedescendant: QuickPickItemActive,
|
|
3847
|
+
childCount: shouldShowScrollbar ? 2 : 1,
|
|
3848
|
+
className: mergeClassNames(List, ContainContent),
|
|
3849
|
+
id: QuickPickItems,
|
|
3850
|
+
onPointerDown: HandlePointerDown,
|
|
3851
|
+
onWheel: HandleWheel,
|
|
3852
|
+
role: ListBox,
|
|
3853
|
+
type: Div
|
|
3854
|
+
}, {
|
|
3855
|
+
childCount: visibleItems.length,
|
|
3856
|
+
className: mergeClassNames(ListItems, ContainContent),
|
|
3857
|
+
type: Div
|
|
3858
|
+
}, ...getQuickPickItemsVirtualDom(visibleItems), ...getScrollBarVirtualDom(scrollBarHeight, scrollBarTop)];
|
|
3859
|
+
};
|
|
3860
|
+
|
|
3861
|
+
const renderItems = newState => {
|
|
3862
|
+
const {
|
|
3863
|
+
scrollBarHeight,
|
|
3864
|
+
scrollBarTop,
|
|
3865
|
+
visibleItems
|
|
3866
|
+
} = newState;
|
|
3867
|
+
const dom = getQuickPickVirtualDom(visibleItems, scrollBarHeight, scrollBarTop);
|
|
3868
|
+
return [SetDom2, dom];
|
|
3869
|
+
};
|
|
3870
|
+
|
|
3871
|
+
const renderIncremental = newState => {
|
|
3872
|
+
const oldDom = renderItems(newState)[1]; // TODO
|
|
3873
|
+
const newDom = renderItems(newState)[1];
|
|
3874
|
+
const patches = diffTree(oldDom, newDom);
|
|
3875
|
+
return [SetPatches, newState.uid, patches];
|
|
3876
|
+
};
|
|
3877
|
+
|
|
3878
|
+
const renderValue = newState => {
|
|
3879
|
+
return ['Viewlet.setValueByName', QuickPickInput, /* value */newState.value];
|
|
3880
|
+
};
|
|
3881
|
+
|
|
3882
|
+
const getRenderer = diffType => {
|
|
3883
|
+
switch (diffType) {
|
|
3884
|
+
case Height:
|
|
3885
|
+
return renderHeight;
|
|
3886
|
+
case RenderCursorOffset:
|
|
3887
|
+
return renderCursorOffset;
|
|
3888
|
+
case RenderFocus:
|
|
3889
|
+
return renderFocus;
|
|
3890
|
+
case RenderFocusedIndex:
|
|
3891
|
+
return renderFocusedIndex;
|
|
3892
|
+
case RenderIncremental:
|
|
3893
|
+
return renderIncremental;
|
|
3894
|
+
case RenderItems:
|
|
3895
|
+
return renderItems;
|
|
3896
|
+
case RenderValue:
|
|
3897
|
+
return renderValue;
|
|
3898
|
+
default:
|
|
3899
|
+
throw new Error('unknown renderer');
|
|
3900
|
+
}
|
|
3901
|
+
};
|
|
3902
|
+
|
|
3903
|
+
const applyRender = (oldState, newState, diffResult) => {
|
|
3904
|
+
const commands = [];
|
|
3905
|
+
const viewModel = createQuickPickViewModel(oldState, newState);
|
|
3906
|
+
for (const item of diffResult) {
|
|
3907
|
+
if (item === Height) {
|
|
3908
|
+
continue;
|
|
3909
|
+
}
|
|
3910
|
+
if (item === RenderFocusedIndex) {
|
|
3911
|
+
continue;
|
|
3912
|
+
}
|
|
3913
|
+
const fn = getRenderer(item);
|
|
3914
|
+
commands.push(fn(viewModel));
|
|
3915
|
+
}
|
|
3916
|
+
return commands;
|
|
3917
|
+
};
|
|
3918
|
+
|
|
3919
|
+
const render2 = (uid, diffResult) => {
|
|
3920
|
+
const {
|
|
3921
|
+
newState,
|
|
3922
|
+
oldState
|
|
3923
|
+
} = get$1(uid);
|
|
3924
|
+
if (oldState === newState) {
|
|
3925
|
+
return [];
|
|
3926
|
+
}
|
|
3927
|
+
set(uid, newState, newState);
|
|
3928
|
+
const commands = applyRender(oldState, newState, diffResult);
|
|
3929
|
+
return commands;
|
|
3930
|
+
};
|
|
3931
|
+
|
|
3932
|
+
const renderEventListeners = () => {
|
|
3933
|
+
return [{
|
|
3934
|
+
name: HandlePointerDown,
|
|
3935
|
+
params: ['handleClickAt', 'event.clientX', 'event.clientY'],
|
|
3936
|
+
preventDefault: true
|
|
3937
|
+
}, {
|
|
3938
|
+
name: HandleWheel,
|
|
3939
|
+
params: ['handleWheel', 'event.deltaMode', 'event.deltaY'],
|
|
3940
|
+
passive: true
|
|
3941
|
+
}, {
|
|
3942
|
+
name: HandleBlur,
|
|
3943
|
+
params: ['handleBlur']
|
|
3944
|
+
}, {
|
|
3945
|
+
name: HandleBeforeInput,
|
|
3946
|
+
params: ['handleBeforeInput']
|
|
3947
|
+
}, {
|
|
3948
|
+
name: HandleInput,
|
|
3949
|
+
params: ['handleInput', 'event.target.value']
|
|
3950
|
+
}, {
|
|
3951
|
+
name: HandleFocus,
|
|
3952
|
+
params: ['handleFocus']
|
|
3953
|
+
}];
|
|
3954
|
+
};
|
|
3955
|
+
|
|
3956
|
+
const selectCurrentIndex = state => {
|
|
3957
|
+
const {
|
|
3958
|
+
focusedIndex
|
|
3959
|
+
} = state;
|
|
3960
|
+
return selectIndex(state, focusedIndex);
|
|
3961
|
+
};
|
|
3962
|
+
|
|
3963
|
+
const findLabelIndex = (items, label) => {
|
|
3964
|
+
for (let i = 0; i < items.length; i++) {
|
|
3965
|
+
if (items[i].label === label) {
|
|
3966
|
+
return i;
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
return -1;
|
|
3970
|
+
};
|
|
3971
|
+
|
|
3972
|
+
const selectItem = async (state, label) => {
|
|
3973
|
+
string(label);
|
|
3974
|
+
const index = findLabelIndex(state.items, label);
|
|
3975
|
+
if (index === -1) {
|
|
3976
|
+
return state;
|
|
3977
|
+
}
|
|
3978
|
+
return selectIndex(state, index);
|
|
3979
|
+
};
|
|
3980
|
+
|
|
3981
|
+
const showQuickInput = async ({
|
|
3982
|
+
ignoreFocusOut,
|
|
3983
|
+
initialValue,
|
|
3984
|
+
waitUntil
|
|
3985
|
+
}) => {
|
|
3986
|
+
// TODO ask renderer worker to create quickpick instance, with given options
|
|
3987
|
+
const picks = [];
|
|
3988
|
+
// const id=QuickPickCallbacks.registerCallback()
|
|
3989
|
+
await invoke$1('QuickPick.showCustom', picks, {
|
|
3990
|
+
ignoreFocusOut,
|
|
3991
|
+
initialValue,
|
|
3992
|
+
waitUntil
|
|
3993
|
+
});
|
|
3994
|
+
return {
|
|
3995
|
+
canceled: false,
|
|
3996
|
+
inputValue: ''
|
|
3997
|
+
};
|
|
3998
|
+
};
|
|
3999
|
+
|
|
4000
|
+
const commandMap = {
|
|
4001
|
+
'QuickPick.addMenuEntries': add,
|
|
4002
|
+
'QuickPick.close': close,
|
|
4003
|
+
'QuickPick.create2': create$8,
|
|
4004
|
+
'QuickPick.diff2': diff2,
|
|
4005
|
+
'QuickPick.dispose': dispose,
|
|
4006
|
+
'QuickPick.executeCallback': executeCallback,
|
|
4007
|
+
'QuickPick.focusFirst': wrapCommand(focusFirst),
|
|
4008
|
+
'QuickPick.focusIndex': wrapCommand(focusIndex),
|
|
4009
|
+
'QuickPick.focusLast': wrapCommand(focusLast),
|
|
4010
|
+
'QuickPick.focusNext': wrapCommand(focusNext),
|
|
4011
|
+
'QuickPick.focusPrevious': wrapCommand(focusPrevious),
|
|
4012
|
+
'QuickPick.getCommandIds': getCommandIds,
|
|
4013
|
+
'QuickPick.getKeyBindings': getKeyBindings,
|
|
4014
|
+
'QuickPick.handleBeforeInput': wrapCommand(handleBeforeInput),
|
|
4015
|
+
'QuickPick.handleBlur': wrapCommand(handleBlur),
|
|
4016
|
+
'QuickPick.handleClickAt': wrapCommand(handleClickAt),
|
|
4017
|
+
'QuickPick.handleFocus': wrapCommand(handleFocus),
|
|
4018
|
+
'QuickPick.handleInput': wrapCommand(handleInput),
|
|
4019
|
+
'QuickPick.handleMessagePort': handleMessagePort,
|
|
4020
|
+
'QuickPick.handleWheel': wrapCommand(handleWheel),
|
|
4021
|
+
'QuickPick.initialize': initialize,
|
|
4022
|
+
'QuickPick.loadContent': wrapCommand(loadContent),
|
|
4023
|
+
'QuickPick.render2': render2,
|
|
4024
|
+
'QuickPick.renderEventListeners': renderEventListeners,
|
|
4025
|
+
'QuickPick.selectCurrentIndex': wrapCommand(selectCurrentIndex),
|
|
4026
|
+
'QuickPick.selectIndex': wrapCommand(selectIndex),
|
|
4027
|
+
'QuickPick.selectItem': wrapCommand(selectItem),
|
|
4028
|
+
'QuickPick.setDeltaY': wrapCommand(setDeltaY),
|
|
4029
|
+
'QuickPick.setValue': wrapCommand(setValue),
|
|
4030
|
+
'QuickPick.showQuickInput': showQuickInput
|
|
4031
|
+
};
|
|
4032
|
+
|
|
4033
|
+
const initializeEditorWorker = async () => {
|
|
4034
|
+
const rpc = await create$1({
|
|
4035
|
+
commandMap: {},
|
|
4036
|
+
async send(port) {
|
|
4037
|
+
await sendMessagePortToEditorWorker(port, 0);
|
|
4038
|
+
}
|
|
4039
|
+
});
|
|
4040
|
+
set$2(rpc);
|
|
4041
|
+
};
|
|
4042
|
+
|
|
4043
|
+
const initializeRendererWorker = async () => {
|
|
4044
|
+
const rpc = await create({
|
|
4045
|
+
commandMap: commandMap
|
|
4046
|
+
});
|
|
4047
|
+
set$1(rpc);
|
|
4048
|
+
};
|
|
4049
|
+
|
|
4050
|
+
const Memfs = 'memfs';
|
|
4051
|
+
const Html = 'html';
|
|
4052
|
+
const Fetch = 'fetch';
|
|
4053
|
+
const File = 'file';
|
|
4054
|
+
const Default = '';
|
|
4055
|
+
|
|
4056
|
+
const searchFile$3 = async uri => {
|
|
4057
|
+
return invoke$1('ExtensionHost.searchFileWithMemory', uri);
|
|
4058
|
+
};
|
|
4059
|
+
|
|
4060
|
+
// TODO simplify code
|
|
4061
|
+
// 1. don't have playground prefix in fileMap json
|
|
4062
|
+
// 2. remove code here that removes the prefix
|
|
4063
|
+
const searchFile$2 = async path => {
|
|
4064
|
+
return invoke$1('ExtensionHost.searchFileWithFetch', path);
|
|
4065
|
+
};
|
|
4066
|
+
|
|
4067
|
+
const searchFile$1 = async uri => {
|
|
4068
|
+
return invoke$1('ExtensionHost.searchFileWithHtml', uri);
|
|
4069
|
+
};
|
|
4070
|
+
|
|
4071
|
+
const getFileSearchRipGrepArgs = () => {
|
|
4072
|
+
const ripGrepArgs = ['--files', '--sort-files', '--hidden', '--glob', '!.git'];
|
|
4073
|
+
return ripGrepArgs;
|
|
4074
|
+
};
|
|
4075
|
+
|
|
4076
|
+
const invoke = (method, ...params) => {
|
|
4077
|
+
return invoke$1('SearchProcess.invoke', method, ...params);
|
|
4078
|
+
};
|
|
4079
|
+
|
|
4080
|
+
// TODO create direct connection from electron to file search worker using message ports
|
|
4081
|
+
|
|
4082
|
+
const searchFile = async (path, value, prepare) => {
|
|
4083
|
+
const ripGrepArgs = getFileSearchRipGrepArgs();
|
|
4084
|
+
const options = {
|
|
4085
|
+
limit: 9_999_999,
|
|
4086
|
+
ripGrepArgs,
|
|
4087
|
+
searchPath: path
|
|
4088
|
+
};
|
|
4089
|
+
const stdout = await invoke('SearchFile.searchFile', options);
|
|
4090
|
+
const lines = splitLines$2(stdout);
|
|
4091
|
+
return lines;
|
|
4092
|
+
};
|
|
4093
|
+
|
|
4094
|
+
const searchModules = {
|
|
4095
|
+
[Default]: searchFile,
|
|
4096
|
+
[Fetch]: searchFile$2,
|
|
4097
|
+
[File]: searchFile,
|
|
4098
|
+
[Html]: searchFile$1,
|
|
4099
|
+
[Memfs]: searchFile$3
|
|
4100
|
+
};
|
|
4101
|
+
|
|
4102
|
+
const listen = async () => {
|
|
4103
|
+
Object.assign(commandMapRef, commandMap);
|
|
4104
|
+
registerCommands(commandMap);
|
|
4105
|
+
register(searchModules);
|
|
4106
|
+
await Promise.all([initializeRendererWorker(), initializeEditorWorker()]);
|
|
4107
|
+
};
|
|
4108
|
+
|
|
4109
|
+
const main = async () => {
|
|
4110
|
+
await listen();
|
|
4111
|
+
};
|
|
4112
|
+
|
|
4113
|
+
main();
|