@theia/keymaps 1.67.0-next.13 → 1.67.0-next.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +2 -2
  2. package/package.json +6 -6
  3. package/lib/browser/index.d.ts +0 -4
  4. package/lib/browser/index.d.ts.map +0 -1
  5. package/lib/browser/index.js +0 -22
  6. package/lib/browser/index.js.map +0 -1
  7. package/lib/browser/keybinding-schema-updater.d.ts +0 -78
  8. package/lib/browser/keybinding-schema-updater.d.ts.map +0 -1
  9. package/lib/browser/keybinding-schema-updater.js +0 -109
  10. package/lib/browser/keybinding-schema-updater.js.map +0 -1
  11. package/lib/browser/keybindings-widget.d.ts +0 -276
  12. package/lib/browser/keybindings-widget.d.ts.map +0 -1
  13. package/lib/browser/keybindings-widget.js +0 -815
  14. package/lib/browser/keybindings-widget.js.map +0 -1
  15. package/lib/browser/keymaps-frontend-contribution.d.ts +0 -38
  16. package/lib/browser/keymaps-frontend-contribution.d.ts.map +0 -1
  17. package/lib/browser/keymaps-frontend-contribution.js +0 -286
  18. package/lib/browser/keymaps-frontend-contribution.js.map +0 -1
  19. package/lib/browser/keymaps-frontend-module.d.ts +0 -6
  20. package/lib/browser/keymaps-frontend-module.d.ts.map +0 -1
  21. package/lib/browser/keymaps-frontend-module.js +0 -46
  22. package/lib/browser/keymaps-frontend-module.js.map +0 -1
  23. package/lib/browser/keymaps-monaco-contribution.d.ts +0 -2
  24. package/lib/browser/keymaps-monaco-contribution.d.ts.map +0 -1
  25. package/lib/browser/keymaps-monaco-contribution.js +0 -28
  26. package/lib/browser/keymaps-monaco-contribution.js.map +0 -1
  27. package/lib/browser/keymaps-service.d.ts +0 -62
  28. package/lib/browser/keymaps-service.d.ts.map +0 -1
  29. package/lib/browser/keymaps-service.js +0 -224
  30. package/lib/browser/keymaps-service.js.map +0 -1
  31. package/lib/package.spec.d.ts +0 -1
  32. package/lib/package.spec.d.ts.map +0 -1
  33. package/lib/package.spec.js +0 -26
  34. package/lib/package.spec.js.map +0 -1
@@ -1,815 +0,0 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2018 Ericsson and others.
4
- //
5
- // This program and the accompanying materials are made available under the
6
- // terms of the Eclipse Public License v. 2.0 which is available at
7
- // http://www.eclipse.org/legal/epl-2.0.
8
- //
9
- // This Source Code may also be made available under the following Secondary
10
- // Licenses when the conditions for such availability set forth in the Eclipse
11
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
- // with the GNU Classpath Exception which is available at
13
- // https://www.gnu.org/software/classpath/license.html.
14
- //
15
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
- // *****************************************************************************
17
- var KeybindingWidget_1;
18
- Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.KeybindingWidget = exports.KeybindingItem = void 0;
20
- const tslib_1 = require("tslib");
21
- const React = require("@theia/core/shared/react");
22
- const debounce = require("@theia/core/shared/lodash.debounce");
23
- const fuzzy = require("@theia/core/shared/fuzzy");
24
- const inversify_1 = require("@theia/core/shared/inversify");
25
- const event_1 = require("@theia/core/lib/common/event");
26
- const command_1 = require("@theia/core/lib/common/command");
27
- const react_widget_1 = require("@theia/core/lib/browser/widgets/react-widget");
28
- const browser_1 = require("@theia/core/lib/browser");
29
- const keymaps_service_1 = require("./keymaps-service");
30
- const alert_message_1 = require("@theia/core/lib/browser/widgets/alert-message");
31
- const core_1 = require("@theia/core");
32
- const nls_1 = require("@theia/core/lib/common/nls");
33
- var KeybindingItem;
34
- (function (KeybindingItem) {
35
- function is(arg) {
36
- return (0, core_1.isObject)(arg) && 'command' in arg && 'labels' in arg;
37
- }
38
- KeybindingItem.is = is;
39
- function keybinding(item) {
40
- var _a;
41
- return (_a = item.keybinding) !== null && _a !== void 0 ? _a : {
42
- command: item.command.id,
43
- keybinding: ''
44
- };
45
- }
46
- KeybindingItem.keybinding = keybinding;
47
- })(KeybindingItem || (exports.KeybindingItem = KeybindingItem = {}));
48
- let KeybindingWidget = KeybindingWidget_1 = class KeybindingWidget extends react_widget_1.ReactWidget {
49
- constructor(options) {
50
- super(options);
51
- /**
52
- * The list of all available keybindings.
53
- */
54
- this.items = [];
55
- /**
56
- * The current user search query.
57
- */
58
- this.query = '';
59
- /**
60
- * The regular expression used to extract values between fuzzy results.
61
- */
62
- this.regexp = /<match>(.*?)<\/match>/g;
63
- /**
64
- * The regular expression used to extract values between the keybinding separator.
65
- */
66
- this.keybindingSeparator = /<match>\+<\/match>/g;
67
- /**
68
- * The fuzzy search options.
69
- * The `pre` and `post` options are used to wrap fuzzy matches.
70
- */
71
- this.fuzzyOptions = {
72
- pre: '<match>',
73
- post: '</match>',
74
- };
75
- this.onDidUpdateEmitter = new event_1.Emitter();
76
- this.onDidUpdate = this.onDidUpdateEmitter.event;
77
- this.onRenderCallbacks = new core_1.DisposableCollection();
78
- this.onRender = () => this.onRenderCallbacks.dispose();
79
- /**
80
- * Search keybindings.
81
- */
82
- this.searchKeybindings = debounce(() => this.doSearchKeybindings(), 50);
83
- this.updateItemsAndRerender = debounce(() => {
84
- this.items = this.getItems();
85
- this.update();
86
- if (this.hasSearch()) {
87
- this.doSearchKeybindings();
88
- }
89
- }, 100, { leading: false, trailing: true });
90
- this.onRender = this.onRender.bind(this);
91
- }
92
- /**
93
- * Initialize the widget.
94
- */
95
- init() {
96
- this.id = KeybindingWidget_1.ID;
97
- this.title.label = KeybindingWidget_1.LABEL;
98
- this.title.caption = KeybindingWidget_1.LABEL;
99
- this.title.iconClass = (0, browser_1.codicon)('three-bars');
100
- this.title.closable = true;
101
- this.updateItemsAndRerender();
102
- // Listen to changes made in the `keymaps.json` and update the view accordingly.
103
- if (this.keymapsService.onDidChangeKeymaps) {
104
- this.toDispose.push(this.keymapsService.onDidChangeKeymaps(() => {
105
- this.items = this.getItems();
106
- this.doSearchKeybindings();
107
- }));
108
- }
109
- this.toDispose.push(this.keybindingRegistry.onKeybindingsChanged(this.updateItemsAndRerender));
110
- }
111
- /**
112
- * Determine if there currently is a search term.
113
- * @returns `true` if a search term is present.
114
- */
115
- hasSearch() {
116
- return !!this.query.length;
117
- }
118
- /**
119
- * Clear the search and reset the view.
120
- */
121
- clearSearch() {
122
- const search = this.findSearchField();
123
- if (search) {
124
- search.value = '';
125
- this.query = '';
126
- this.doSearchKeybindings();
127
- }
128
- }
129
- /**
130
- * Show keybinding items with the same key sequence as the given item.
131
- * @param item the keybinding item
132
- */
133
- showSameKeybindings(item) {
134
- const keybinding = item.keybinding;
135
- if (keybinding) {
136
- const search = this.findSearchField();
137
- if (search) {
138
- const query = `"${this.keybindingRegistry.acceleratorFor(keybinding, '+', true).join(' ')}"`;
139
- search.value = query;
140
- this.query = query;
141
- this.doSearchKeybindings();
142
- }
143
- }
144
- }
145
- onActivateRequest(msg) {
146
- super.onActivateRequest(msg);
147
- this.focusInputField();
148
- }
149
- /**
150
- * Perform a search based on the user's search query.
151
- */
152
- doSearchKeybindings() {
153
- this.onDidUpdateEmitter.fire(undefined);
154
- const searchField = this.findSearchField();
155
- this.query = searchField ? searchField.value.trim().toLocaleLowerCase() : '';
156
- let query = this.query;
157
- const startsWithQuote = query.startsWith('"');
158
- const endsWithQuote = query.endsWith('"');
159
- const matchKeybindingOnly = startsWithQuote && endsWithQuote;
160
- if (startsWithQuote) {
161
- query = query.slice(1);
162
- }
163
- if (endsWithQuote) {
164
- query = query.slice(0, -1);
165
- }
166
- const queryItems = query.split(/[+\s]/);
167
- this.items.forEach(item => {
168
- let matched = !this.query;
169
- if (!matchKeybindingOnly) {
170
- matched = this.formatAndMatchCommand(item) || matched;
171
- }
172
- matched = this.formatAndMatchKeybinding(item, queryItems, matchKeybindingOnly) || matched;
173
- if (!matchKeybindingOnly) {
174
- matched = this.formatAndMatchContext(item) || matched;
175
- matched = this.formatAndMatchSource(item) || matched;
176
- }
177
- item.visible = matched;
178
- });
179
- this.update();
180
- }
181
- formatAndMatchCommand(item) {
182
- item.labels.command = this.toRenderableLabel(item.labels.command.value);
183
- return Boolean(item.labels.command.segments);
184
- }
185
- formatAndMatchKeybinding(item, queryItems, exactMatch) {
186
- if (item.keybinding) {
187
- const unmatchedTerms = queryItems.filter(Boolean);
188
- const segments = this.keybindingRegistry.resolveKeybinding(item.keybinding).reduce((collection, code, codeIndex) => {
189
- if (codeIndex !== 0) {
190
- // Two non-breaking spaces.
191
- collection.push({ value: '\u00a0\u00a0', match: false, key: false });
192
- }
193
- const displayChunks = this.keybindingRegistry.componentsForKeyCode(code);
194
- const matchChunks = core_1.isOSX ? this.keybindingRegistry.componentsForKeyCode(code, true) : displayChunks;
195
- displayChunks.forEach((chunk, chunkIndex) => {
196
- if (chunkIndex !== 0) {
197
- collection.push({ value: '+', match: false, key: false });
198
- }
199
- const indexOfTerm = unmatchedTerms.indexOf(matchChunks[chunkIndex].toLocaleLowerCase());
200
- const chunkMatches = indexOfTerm > -1;
201
- if (chunkMatches) {
202
- unmatchedTerms.splice(indexOfTerm, 1);
203
- }
204
- collection.push({ value: chunk, match: chunkMatches, key: true });
205
- });
206
- return collection;
207
- }, []);
208
- item.labels.keybinding = { value: item.labels.keybinding.value, segments };
209
- if (unmatchedTerms.length) {
210
- return false;
211
- }
212
- if (exactMatch) {
213
- return !segments.some(segment => segment.key && !segment.match);
214
- }
215
- return true;
216
- }
217
- item.labels.keybinding = { value: '' };
218
- return false;
219
- }
220
- formatAndMatchContext(item) {
221
- item.labels.context = this.toRenderableLabel(item.labels.context.value);
222
- return Boolean(item.labels.context.segments);
223
- }
224
- formatAndMatchSource(item) {
225
- item.labels.source = this.toRenderableLabel(item.labels.source.value);
226
- return Boolean(item.labels.source.segments);
227
- }
228
- toRenderableLabel(label, query = this.query) {
229
- if (label && query) {
230
- const fuzzyMatch = fuzzy.match(query, label, this.fuzzyOptions);
231
- if (fuzzyMatch) {
232
- return {
233
- value: label,
234
- segments: fuzzyMatch.rendered.split(this.fuzzyOptions.pre).reduce((collection, segment) => {
235
- const [maybeMatch, notMatch] = segment.split(this.fuzzyOptions.post);
236
- if (notMatch === undefined) {
237
- collection.push({ value: maybeMatch, match: false });
238
- }
239
- else {
240
- collection.push({ value: maybeMatch, match: true }, { value: notMatch, match: false });
241
- }
242
- return collection;
243
- }, [])
244
- };
245
- }
246
- }
247
- return { value: label };
248
- }
249
- /**
250
- * Get the search input if available.
251
- * @returns the search input if available.
252
- */
253
- findSearchField() {
254
- return document.getElementById('search-kb');
255
- }
256
- /**
257
- * Set the focus the search input field if available.
258
- */
259
- focusInputField() {
260
- const input = document.getElementById('search-kb');
261
- if (input) {
262
- input.focus();
263
- input.select();
264
- }
265
- }
266
- /**
267
- * Render the view.
268
- */
269
- render() {
270
- return React.createElement("div", { id: 'kb-main-container' },
271
- this.renderSearch(),
272
- (this.items.length > 0) ? this.renderTable() : this.renderMessage());
273
- }
274
- /**
275
- * Render the search container with the search input.
276
- */
277
- renderSearch() {
278
- return React.createElement("div", null,
279
- React.createElement("div", { className: 'search-kb-container' },
280
- React.createElement("input", { id: 'search-kb', ref: this.onRender, className: `theia-input${(this.items.length > 0) ? '' : ' no-kb'}`, type: 'text', spellCheck: false, placeholder: nls_1.nls.localizeByDefault('Type to search in keybindings'), autoComplete: 'off', onKeyUp: this.searchKeybindings })));
281
- }
282
- /**
283
- * Render the warning message when no search results are found.
284
- */
285
- renderMessage() {
286
- return React.createElement(alert_message_1.AlertMessage, { type: 'WARNING', header: 'No results found!' });
287
- }
288
- /**
289
- * Render the keybindings table.
290
- */
291
- renderTable() {
292
- return React.createElement("div", { id: 'kb-table-container' },
293
- React.createElement("div", { className: 'kb' },
294
- React.createElement("table", null,
295
- React.createElement("thead", null,
296
- React.createElement("tr", null,
297
- React.createElement("th", { className: 'th-action' }),
298
- React.createElement("th", { className: 'th-label' }, nls_1.nls.localizeByDefault('Command')),
299
- React.createElement("th", { className: 'th-keybinding' }, nls_1.nls.localizeByDefault('Keybinding')),
300
- React.createElement("th", { className: 'th-context' }, nls_1.nls.localizeByDefault('When')),
301
- React.createElement("th", { className: 'th-source' }, nls_1.nls.localizeByDefault('Source')))),
302
- React.createElement("tbody", null, this.renderRows()))));
303
- }
304
- /**
305
- * Render the table rows.
306
- */
307
- renderRows() {
308
- return React.createElement(React.Fragment, null, this.items.map((item, index) => item.visible !== false && this.renderRow(item, index)));
309
- }
310
- renderRow(item, index) {
311
- const { command, keybinding } = item;
312
- // TODO get rid of array functions in event handlers
313
- return React.createElement("tr", { className: 'kb-item-row', key: index, onDoubleClick: event => this.handleItemDoubleClick(item, index, event), onClick: event => this.handleItemClick(item, index, event), onContextMenu: event => this.handleItemContextMenu(item, index, event) },
314
- React.createElement("td", { className: 'kb-actions' }, this.renderActions(item)),
315
- React.createElement("td", { className: 'kb-label', title: this.getCommandLabel(command) }, this.renderMatchedData(item.labels.command)),
316
- React.createElement("td", { title: this.getKeybindingLabel(keybinding), className: 'kb-keybinding monaco-keybinding' }, this.renderKeybinding(item)),
317
- React.createElement("td", { className: 'kb-context', title: this.getContextLabel(keybinding) },
318
- React.createElement("code", null, this.renderMatchedData(item.labels.context))),
319
- React.createElement("td", { className: 'kb-source', title: this.getScopeLabel(keybinding) },
320
- React.createElement("code", { className: 'td-source' }, this.renderMatchedData(item.labels.source))));
321
- }
322
- handleItemClick(item, index, event) {
323
- event.preventDefault();
324
- this.selectItem(item, index, event.currentTarget);
325
- }
326
- handleItemDoubleClick(item, index, event) {
327
- event.preventDefault();
328
- this.selectItem(item, index, event.currentTarget);
329
- this.editKeybinding(item);
330
- }
331
- handleItemContextMenu(item, index, event) {
332
- event.preventDefault();
333
- this.selectItem(item, index, event.currentTarget);
334
- this.contextMenuRenderer.render({
335
- menuPath: KeybindingWidget_1.CONTEXT_MENU,
336
- anchor: event.nativeEvent,
337
- args: [item, this],
338
- context: event.currentTarget
339
- });
340
- }
341
- selectItem(item, index, element) {
342
- var _a;
343
- if (!element.classList.contains(browser_1.SELECTED_CLASS)) {
344
- const selected = (_a = element.parentElement) === null || _a === void 0 ? void 0 : _a.getElementsByClassName(browser_1.SELECTED_CLASS)[0];
345
- if (selected) {
346
- selected.classList.remove(browser_1.SELECTED_CLASS);
347
- }
348
- element.classList.add(browser_1.SELECTED_CLASS);
349
- }
350
- }
351
- /**
352
- * Render the actions container with action icons.
353
- * @param item the keybinding item for the row.
354
- */
355
- renderActions(item) {
356
- return React.createElement("span", { className: 'kb-actions-icons' },
357
- this.renderEdit(item),
358
- this.renderReset(item));
359
- }
360
- /**
361
- * Render the edit action used to update a keybinding.
362
- * @param item the keybinding item for the row.
363
- */
364
- renderEdit(item) {
365
- return React.createElement("a", { title: 'Edit Keybinding', href: '#', onClick: e => {
366
- e.preventDefault();
367
- this.editKeybinding(item);
368
- } },
369
- React.createElement("i", { className: `${(0, browser_1.codicon)('edit', true)} kb-action-item` }));
370
- }
371
- /**
372
- * Render the reset action to reset the custom keybinding.
373
- * Only visible if a keybinding has a `user` scope.
374
- * @param item the keybinding item for the row.
375
- */
376
- renderReset(item) {
377
- return this.canResetKeybinding(item)
378
- ? React.createElement("a", { title: 'Reset Keybinding', href: '#', onClick: e => {
379
- e.preventDefault();
380
- this.resetKeybinding(item);
381
- } },
382
- React.createElement("i", { className: `${(0, browser_1.codicon)('discard', true)} kb-action-item` })) : '';
383
- }
384
- /**
385
- * Render the keybinding.
386
- * @param keybinding the keybinding value.
387
- */
388
- renderKeybinding(keybinding) {
389
- if (!keybinding.keybinding) {
390
- return undefined;
391
- }
392
- if (keybinding.labels.keybinding.segments) {
393
- return keybinding.labels.keybinding.segments.map((segment, index) => {
394
- if (segment.key) {
395
- return React.createElement("span", { key: index, className: 'monaco-keybinding-key' },
396
- React.createElement("span", { className: `${segment.match ? 'fuzzy-match' : ''}` }, segment.value));
397
- }
398
- else {
399
- return React.createElement("span", { key: index, className: 'monaco-keybinding-separator' }, segment.value);
400
- }
401
- });
402
- }
403
- console.warn('Unexpectedly encountered a keybinding without segment divisions');
404
- return keybinding.labels.keybinding.value;
405
- }
406
- /**
407
- * Get the list of keybinding items.
408
- *
409
- * @returns the list of keybinding items.
410
- */
411
- getItems() {
412
- // Sort the commands alphabetically.
413
- const commands = this.commandRegistry.commands;
414
- const items = [];
415
- // Build the keybinding items.
416
- for (let i = 0; i < commands.length; i++) {
417
- const command = commands[i];
418
- // Skip internal commands prefixed by `_`.
419
- if (command.id.startsWith('_')) {
420
- continue;
421
- }
422
- const keybindings = this.keybindingRegistry.getKeybindingsForCommand(command.id);
423
- keybindings.forEach(keybinding => {
424
- const item = this.createKeybindingItem(command, keybinding);
425
- items.push(item);
426
- });
427
- // we might not have any keybindings for the command
428
- if (keybindings.length < 1) {
429
- const item = this.createKeybindingItem(command);
430
- items.push(item);
431
- }
432
- }
433
- return this.sortKeybindings(items);
434
- }
435
- createKeybindingItem(command, keybinding) {
436
- const item = {
437
- command,
438
- keybinding,
439
- labels: {
440
- id: { value: command.id },
441
- command: { value: this.getCommandLabel(command) },
442
- keybinding: { value: this.getKeybindingLabel(keybinding) || '' },
443
- context: { value: this.getContextLabel(keybinding) || '' },
444
- source: { value: this.getScopeLabel(keybinding) || '' }
445
- }
446
- };
447
- this.formatAndMatchCommand(item);
448
- this.formatAndMatchKeybinding(item, []);
449
- this.formatAndMatchContext(item);
450
- this.formatAndMatchSource(item);
451
- return item;
452
- }
453
- /**
454
- * @returns the input array, sorted.
455
- * The sort priority is as follows: items with keybindings before those without, then alphabetical by command.
456
- */
457
- sortKeybindings(bindings) {
458
- return bindings.sort((a, b) => {
459
- if (a.keybinding && !b.keybinding) {
460
- return -1;
461
- }
462
- if (b.keybinding && !a.keybinding) {
463
- return 1;
464
- }
465
- return this.compareItem(a.command, b.command);
466
- });
467
- }
468
- /**
469
- * Get the human-readable label for a given command.
470
- * @param command the command.
471
- *
472
- * @returns a human-readable label for the given command.
473
- */
474
- getCommandLabel(command) {
475
- if (command.label) {
476
- // Prefix the command label with the category if it exists, else return the simple label.
477
- return command.category ? `${command.category}: ${command.label}` : command.label;
478
- }
479
- return command.id;
480
- }
481
- getKeybindingLabel(keybinding) {
482
- return keybinding && keybinding.keybinding;
483
- }
484
- getContextLabel(keybinding) {
485
- return keybinding ? keybinding.context || keybinding.when : undefined;
486
- }
487
- getScopeLabel(keybinding) {
488
- let scope = keybinding && keybinding.scope;
489
- if (scope !== undefined) {
490
- if (scope < browser_1.KeybindingScope.USER) {
491
- scope = browser_1.KeybindingScope.DEFAULT;
492
- }
493
- return browser_1.KeybindingScope[scope].toLocaleLowerCase();
494
- }
495
- return undefined;
496
- }
497
- /**
498
- * Compare two commands.
499
- * - Commands with a label should be prioritized and alphabetically sorted.
500
- * - Commands without a label (id) should be placed at the bottom.
501
- * @param a the first command.
502
- * @param b the second command.
503
- *
504
- * @returns an integer indicating whether `a` comes before, after or is equivalent to `b`.
505
- * - returns `-1` if `a` occurs before `b`.
506
- * - returns `1` if `a` occurs after `b`.
507
- * - returns `0` if they are equivalent.
508
- */
509
- compareItem(a, b) {
510
- const labelA = this.getCommandLabel(a);
511
- const labelB = this.getCommandLabel(b);
512
- if (labelA === a.id && labelB === b.id) {
513
- return labelA.toLowerCase().localeCompare(labelB.toLowerCase());
514
- }
515
- if (labelA === a.id) {
516
- return 1;
517
- }
518
- if (labelB === b.id) {
519
- return -1;
520
- }
521
- return labelA.toLowerCase().localeCompare(labelB.toLowerCase());
522
- }
523
- /**
524
- * Prompt users to update the keybinding for the given command.
525
- * @param item the keybinding item.
526
- */
527
- editKeybinding(item) {
528
- const command = item.command.id;
529
- const oldKeybinding = item.keybinding;
530
- const dialog = new EditKeybindingDialog({
531
- title: nls_1.nls.localize('theia/keymaps/editKeybindingTitle', 'Edit Keybinding for {0}', item.labels.command.value),
532
- maxWidth: 400,
533
- initialValue: oldKeybinding === null || oldKeybinding === void 0 ? void 0 : oldKeybinding.keybinding,
534
- validate: newKeybinding => this.validateKeybinding(command, oldKeybinding === null || oldKeybinding === void 0 ? void 0 : oldKeybinding.keybinding, newKeybinding),
535
- }, this.keymapsService, item, this.canResetKeybinding(item));
536
- dialog.open().then(async (keybinding) => {
537
- if (keybinding && keybinding !== (oldKeybinding === null || oldKeybinding === void 0 ? void 0 : oldKeybinding.keybinding)) {
538
- await this.keymapsService.setKeybinding({
539
- ...oldKeybinding,
540
- command,
541
- keybinding
542
- }, oldKeybinding);
543
- }
544
- });
545
- }
546
- /**
547
- * Prompt users to update when expression for the given keybinding.
548
- * @param item the keybinding item
549
- */
550
- editWhenExpression(item) {
551
- const keybinding = item.keybinding;
552
- if (!keybinding) {
553
- return;
554
- }
555
- const dialog = new browser_1.SingleTextInputDialog({
556
- title: nls_1.nls.localize('theia/keymaps/editWhenExpressionTitle', 'Edit When Expression for {0}', item.labels.command.value),
557
- maxWidth: 400,
558
- initialValue: keybinding.when
559
- });
560
- dialog.open().then(async (when) => {
561
- var _a;
562
- if (when === undefined) {
563
- return; // cancelled by the user
564
- }
565
- if (when !== ((_a = keybinding.when) !== null && _a !== void 0 ? _a : '')) {
566
- if (when === '') {
567
- when = undefined;
568
- }
569
- await this.keymapsService.setKeybinding({
570
- ...keybinding,
571
- when
572
- }, keybinding);
573
- }
574
- });
575
- }
576
- /**
577
- * Prompt users to add a keybinding for the given command.
578
- * @param item the keybinding item
579
- */
580
- addKeybinding(item) {
581
- const command = item.command.id;
582
- const dialog = new browser_1.SingleTextInputDialog({
583
- title: nls_1.nls.localize('theia/keymaps/addKeybindingTitle', 'Add Keybinding for {0}', item.labels.command.value),
584
- maxWidth: 400,
585
- validate: newKeybinding => this.validateKeybinding(command, undefined, newKeybinding),
586
- });
587
- dialog.open().then(async (keybinding) => {
588
- if (keybinding) {
589
- await this.keymapsService.setKeybinding({
590
- ...item.keybinding,
591
- command,
592
- keybinding
593
- }, undefined);
594
- }
595
- });
596
- }
597
- /**
598
- * Prompt users for confirmation before resetting.
599
- * @param command the command label.
600
- *
601
- * @returns a Promise which resolves to `true` if a user accepts resetting.
602
- */
603
- async confirmResetKeybinding(item) {
604
- const message = document.createElement('div');
605
- const question = document.createElement('p');
606
- question.textContent = nls_1.nls.localize('theia/keymaps/resetKeybindingConfirmation', 'Do you really want to reset this keybinding to its default value?');
607
- message.append(question);
608
- const info = document.createElement('p');
609
- info.textContent = nls_1.nls.localize('theia/keymaps/resetMultipleKeybindingsWarning', 'If multiple keybindings exist for this command, all of them will be reset.');
610
- message.append(info);
611
- const dialog = new browser_1.ConfirmDialog({
612
- title: nls_1.nls.localize('theia/keymaps/resetKeybindingTitle', 'Reset keybinding for {0}', this.getCommandLabel(item.command)),
613
- msg: message
614
- });
615
- return !!await dialog.open();
616
- }
617
- /**
618
- * Reset the keybinding to its default value.
619
- * @param item the keybinding item.
620
- */
621
- async resetKeybinding(item) {
622
- const confirmed = await this.confirmResetKeybinding(item);
623
- if (confirmed) {
624
- this.keymapsService.removeKeybinding(item.command.id);
625
- }
626
- }
627
- /**
628
- * Whether the keybinding can be reset to its default value.
629
- * @param item the keybinding item
630
- */
631
- canResetKeybinding(item) {
632
- var _a;
633
- return ((_a = item.keybinding) === null || _a === void 0 ? void 0 : _a.scope) === browser_1.KeybindingScope.USER || this.keymapsService.hasKeybinding('-' + item.command.id);
634
- }
635
- /**
636
- * Validate the provided keybinding value against its previous value.
637
- * @param command the command label.
638
- * @param oldKeybinding the old keybinding value.
639
- * @param keybinding the new keybinding value.
640
- *
641
- * @returns the end user message to display.
642
- */
643
- validateKeybinding(command, oldKeybinding, keybinding) {
644
- if (!keybinding) {
645
- return nls_1.nls.localize('theia/keymaps/requiredKeybindingValidation', 'keybinding value is required');
646
- }
647
- try {
648
- const binding = { command, keybinding };
649
- browser_1.KeySequence.parse(keybinding);
650
- if (oldKeybinding === keybinding) {
651
- return ''; // if old and new keybindings match, quietly reject update
652
- }
653
- if (this.keybindingRegistry.containsKeybindingInScope(binding)) {
654
- return nls_1.nls.localize('theia/keymaps/keybindingCollidesValidation', 'keybinding currently collides');
655
- }
656
- return '';
657
- }
658
- catch (error) {
659
- return error;
660
- }
661
- }
662
- /**
663
- * Build the cell data with highlights if applicable.
664
- * @param raw the raw cell value.
665
- *
666
- * @returns the list of cell data.
667
- */
668
- buildCellData(raw) {
669
- const data = [];
670
- if (this.query === '') {
671
- return data;
672
- }
673
- let following = raw;
674
- let leading;
675
- let result;
676
- const regexp = new RegExp(this.regexp);
677
- while (result = regexp.exec(raw)) {
678
- const splitLeftIndex = following.indexOf(result[0]);
679
- const splitRightIndex = splitLeftIndex + result[0].length;
680
- leading = following.slice(0, splitLeftIndex);
681
- following = following.slice(splitRightIndex);
682
- if (leading) {
683
- data.push({ value: leading, highlighted: false });
684
- }
685
- data.push({ value: result[1], highlighted: true });
686
- }
687
- if (following) {
688
- data.push({ value: following, highlighted: false });
689
- }
690
- return data;
691
- }
692
- /**
693
- * Render the fuzzy representation of a matched result.
694
- * @param property one of the `KeybindingItem` properties.
695
- */
696
- renderMatchedData(property) {
697
- if (property.segments) {
698
- return React.createElement(React.Fragment, null, property.segments.map((segment, index) => segment.match
699
- ? React.createElement("span", { key: index, className: 'fuzzy-match' }, segment.value)
700
- : React.createElement("span", { key: index }, segment.value)));
701
- }
702
- return property.value;
703
- }
704
- storeState() {
705
- return { query: this.query };
706
- }
707
- restoreState(oldState) {
708
- if (typeof (oldState === null || oldState === void 0 ? void 0 : oldState.query) === 'string') {
709
- this.onRenderCallbacks.push({
710
- dispose: () => {
711
- const searchField = this.findSearchField();
712
- if (searchField) {
713
- searchField.value = oldState.query;
714
- this.searchKeybindings();
715
- }
716
- }
717
- });
718
- }
719
- }
720
- };
721
- exports.KeybindingWidget = KeybindingWidget;
722
- KeybindingWidget.ID = 'keybindings.view.widget';
723
- KeybindingWidget.LABEL = nls_1.nls.localizeByDefault('Keyboard Shortcuts');
724
- KeybindingWidget.CONTEXT_MENU = ['keybinding-context-menu'];
725
- KeybindingWidget.COPY_MENU = [...KeybindingWidget_1.CONTEXT_MENU, 'a_copy'];
726
- KeybindingWidget.EDIT_MENU = [...KeybindingWidget_1.CONTEXT_MENU, 'b_edit'];
727
- KeybindingWidget.ADD_MENU = [...KeybindingWidget_1.CONTEXT_MENU, 'c_add'];
728
- KeybindingWidget.REMOVE_MENU = [...KeybindingWidget_1.CONTEXT_MENU, 'd_remove'];
729
- KeybindingWidget.SHOW_MENU = [...KeybindingWidget_1.CONTEXT_MENU, 'e_show'];
730
- tslib_1.__decorate([
731
- (0, inversify_1.inject)(command_1.CommandRegistry),
732
- tslib_1.__metadata("design:type", command_1.CommandRegistry)
733
- ], KeybindingWidget.prototype, "commandRegistry", void 0);
734
- tslib_1.__decorate([
735
- (0, inversify_1.inject)(browser_1.KeybindingRegistry),
736
- tslib_1.__metadata("design:type", browser_1.KeybindingRegistry)
737
- ], KeybindingWidget.prototype, "keybindingRegistry", void 0);
738
- tslib_1.__decorate([
739
- (0, inversify_1.inject)(keymaps_service_1.KeymapsService),
740
- tslib_1.__metadata("design:type", keymaps_service_1.KeymapsService)
741
- ], KeybindingWidget.prototype, "keymapsService", void 0);
742
- tslib_1.__decorate([
743
- (0, inversify_1.inject)(browser_1.ContextMenuRenderer),
744
- tslib_1.__metadata("design:type", browser_1.ContextMenuRenderer)
745
- ], KeybindingWidget.prototype, "contextMenuRenderer", void 0);
746
- tslib_1.__decorate([
747
- (0, inversify_1.postConstruct)(),
748
- tslib_1.__metadata("design:type", Function),
749
- tslib_1.__metadata("design:paramtypes", []),
750
- tslib_1.__metadata("design:returntype", void 0)
751
- ], KeybindingWidget.prototype, "init", null);
752
- exports.KeybindingWidget = KeybindingWidget = KeybindingWidget_1 = tslib_1.__decorate([
753
- (0, inversify_1.injectable)(),
754
- tslib_1.__param(0, (0, inversify_1.unmanaged)()),
755
- tslib_1.__metadata("design:paramtypes", [Object])
756
- ], KeybindingWidget);
757
- /**
758
- * Dialog used to edit keybindings, and reset custom keybindings.
759
- */
760
- let EditKeybindingDialog = class EditKeybindingDialog extends browser_1.SingleTextInputDialog {
761
- constructor(props, keymapsService, item, canReset) {
762
- super(props);
763
- this.keymapsService = keymapsService;
764
- this.item = item;
765
- // Add the `Reset` button if the command currently has a custom keybinding.
766
- if (canReset) {
767
- this.appendResetButton();
768
- }
769
- }
770
- onAfterAttach(msg) {
771
- super.onAfterAttach(msg);
772
- if (this.resetButton) {
773
- this.addResetAction(this.resetButton, 'click');
774
- }
775
- }
776
- /**
777
- * Add `Reset` action used to reset a custom keybinding, and close the dialog.
778
- * @param element the HTML element in question.
779
- * @param additionalEventTypes additional event types.
780
- */
781
- addResetAction(element, ...additionalEventTypes) {
782
- this.addKeyListener(element, browser_1.Key.ENTER, () => {
783
- this.reset();
784
- this.close();
785
- }, ...additionalEventTypes);
786
- }
787
- /**
788
- * Create the `Reset` button, and append it to the dialog.
789
- *
790
- * @returns the `Reset` button.
791
- */
792
- appendResetButton() {
793
- // Create the `Reset` button.
794
- const resetButtonTitle = nls_1.nls.localizeByDefault('Reset');
795
- this.resetButton = this.createButton(resetButtonTitle);
796
- // Add the `Reset` button to the dialog control panel, before the `Accept` button.
797
- this.controlPanel.insertBefore(this.resetButton, this.acceptButton);
798
- this.resetButton.title = nls_1.nls.localizeByDefault('Reset Keybinding');
799
- this.resetButton.classList.add('secondary');
800
- return this.resetButton;
801
- }
802
- /**
803
- * Perform keybinding reset.
804
- */
805
- reset() {
806
- this.keymapsService.removeKeybinding(this.item.command.id);
807
- }
808
- };
809
- EditKeybindingDialog = tslib_1.__decorate([
810
- tslib_1.__param(0, (0, inversify_1.inject)(browser_1.SingleTextInputDialogProps)),
811
- tslib_1.__param(1, (0, inversify_1.inject)(keymaps_service_1.KeymapsService)),
812
- tslib_1.__metadata("design:paramtypes", [browser_1.SingleTextInputDialogProps,
813
- keymaps_service_1.KeymapsService, Object, Boolean])
814
- ], EditKeybindingDialog);
815
- //# sourceMappingURL=keybindings-widget.js.map