commands.ts 20.5 KB
Newer Older
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

S
Sandeep Somavarapu 已提交
6 7
import { tmpdir } from 'os';
import { posix } from 'path';
8 9
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
10
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
11
import { IPartService } from 'vs/workbench/services/part/common/partService';
12
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
13 14
import { List } from 'vs/base/browser/ui/list/listWidget';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
15
import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey, ListWidget, WorkbenchListHasSelectionOrFocus } from 'vs/platform/list/browser/listService';
J
Joao Moreno 已提交
16
import { PagedList } from 'vs/base/browser/ui/list/listPaging';
J
Joao Moreno 已提交
17
import { range } from 'vs/base/common/arrays';
J
Joao Moreno 已提交
18
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
19
import { ITree } from 'vs/base/parts/tree/browser/tree';
B
Benjamin Pasero 已提交
20
import { InEditorZenModeContext, NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
21
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
22
import { URI } from 'vs/base/common/uri';
S
Sandeep Somavarapu 已提交
23
import { IDownloadService } from 'vs/platform/download/common/download';
S
Sandeep Somavarapu 已提交
24
import { generateUuid } from 'vs/base/common/uuid';
J
Joao Moreno 已提交
25
import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
J
Joao Moreno 已提交
26
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
27 28 29

// --- List Commands

30 31 32 33 34
function ensureDOMFocus(widget: ListWidget): void {
	// it can happen that one of the commands is executed while
	// DOM focus is within another focusable control within the
	// list/tree item. therefor we should ensure that the
	// list/tree has DOM focus again after the command ran.
J
Joao Moreno 已提交
35
	if (widget && widget.getHTMLElement() !== document.activeElement) {
36 37 38 39
		widget.domFocus();
	}
}

I
isidor 已提交
40
export const QUIT_ID = 'workbench.action.quit';
41 42
export function registerCommands(): void {

43 44 45 46
	function focusDown(accessor: ServicesAccessor, arg2?: number): void {
		const focused = accessor.get(IListService).lastFocusedList;
		const count = typeof arg2 === 'number' ? arg2 : 1;

47 48 49
		// Ensure DOM Focus
		ensureDOMFocus(focused);

50 51 52 53 54
		// List
		if (focused instanceof List || focused instanceof PagedList) {
			const list = focused;

			list.focusNext(count);
I
isidor 已提交
55 56 57 58
			const listFocus = list.getFocus();
			if (listFocus.length) {
				list.reveal(listFocus[0]);
			}
59 60
		}

J
Joao Moreno 已提交
61
		// ObjectTree
J
Joao Moreno 已提交
62
		else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
63 64
			const list = focused;

65 66 67
			const fakeKeyboardEvent = new KeyboardEvent('keydown');
			list.focusNext(count, false, fakeKeyboardEvent);

J
Joao Moreno 已提交
68 69 70 71 72 73
			const listFocus = list.getFocus();
			if (listFocus.length) {
				list.reveal(listFocus[0]);
			}
		}

74 75 76 77 78
		// Tree
		else if (focused) {
			const tree = focused;

			tree.focusNext(count, { origin: 'keyboard' });
79
			tree.reveal(tree.getFocus());
80 81 82
		}
	}

83
	KeybindingsRegistry.registerCommandAndKeybindingRule({
B
Benjamin Pasero 已提交
84
		id: 'list.focusDown',
85
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
86
		when: WorkbenchListFocusContextKey,
87 88 89 90 91
		primary: KeyCode.DownArrow,
		mac: {
			primary: KeyCode.DownArrow,
			secondary: [KeyMod.WinCtrl | KeyCode.KEY_N]
		},
92 93 94
		handler: (accessor, arg2) => focusDown(accessor, arg2)
	});

J
Joao Moreno 已提交
95
	function expandMultiSelection(focused: List<any> | PagedList<any> | ITree | ObjectTree<any, any> | AsyncDataTree<any, any>, previousFocus: any): void {
96 97 98 99 100 101 102 103 104 105 106 107 108 109

		// List
		if (focused instanceof List || focused instanceof PagedList) {
			const list = focused;

			const focus = list.getFocus() ? list.getFocus()[0] : void 0;
			const selection = list.getSelection();
			if (selection && selection.indexOf(focus) >= 0) {
				list.setSelection(selection.filter(s => s !== previousFocus));
			} else {
				list.setSelection(selection.concat(focus));
			}
		}

J
Joao Moreno 已提交
110
		// ObjectTree
J
Joao Moreno 已提交
111
		else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
112 113 114 115
			const list = focused;

			const focus = list.getFocus() ? list.getFocus()[0] : void 0;
			const selection = list.getSelection();
116 117
			const fakeKeyboardEvent = new KeyboardEvent('keydown');

J
Joao Moreno 已提交
118
			if (selection && selection.indexOf(focus) >= 0) {
119
				list.setSelection(selection.filter(s => s !== previousFocus), fakeKeyboardEvent);
J
Joao Moreno 已提交
120
			} else {
121
				list.setSelection(selection.concat(focus), fakeKeyboardEvent);
J
Joao Moreno 已提交
122 123 124
			}
		}

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
		// Tree
		else if (focused) {
			const tree = focused;

			const focus = tree.getFocus();
			const selection = tree.getSelection();
			if (selection && selection.indexOf(focus) >= 0) {
				tree.setSelection(selection.filter(s => s !== previousFocus));
			} else {
				tree.setSelection(selection.concat(focus));
			}
		}
	}

	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.expandSelectionDown',
141
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
142
		when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
143
		primary: KeyMod.Shift | KeyCode.DownArrow,
144
		handler: (accessor, arg2) => {
J
Joao Moreno 已提交
145
			const focused = accessor.get(IListService).lastFocusedList;
146 147

			// List
J
Joao Moreno 已提交
148
			if (focused instanceof List || focused instanceof PagedList || focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
149 150 151 152 153 154 155 156 157 158
				const list = focused;

				// Focus down first
				const previousFocus = list.getFocus() ? list.getFocus()[0] : void 0;
				focusDown(accessor, arg2);

				// Then adjust selection
				expandMultiSelection(focused, previousFocus);
			}

159 160 161 162
			// Tree
			else if (focused) {
				const tree = focused;

163 164 165 166 167 168
				// Focus down first
				const previousFocus = tree.getFocus();
				focusDown(accessor, arg2);

				// Then adjust selection
				expandMultiSelection(focused, previousFocus);
169 170 171 172
			}
		}
	});

173 174 175 176
	function focusUp(accessor: ServicesAccessor, arg2?: number): void {
		const focused = accessor.get(IListService).lastFocusedList;
		const count = typeof arg2 === 'number' ? arg2 : 1;

177 178 179
		// Ensure DOM Focus
		ensureDOMFocus(focused);

180 181 182 183 184
		// List
		if (focused instanceof List || focused instanceof PagedList) {
			const list = focused;

			list.focusPrevious(count);
I
isidor 已提交
185 186 187 188
			const listFocus = list.getFocus();
			if (listFocus.length) {
				list.reveal(listFocus[0]);
			}
189 190
		}

J
Joao Moreno 已提交
191
		// ObjectTree
J
Joao Moreno 已提交
192
		else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
193 194
			const list = focused;

195 196 197
			const fakeKeyboardEvent = new KeyboardEvent('keydown');
			list.focusPrevious(count, false, fakeKeyboardEvent);

J
Joao Moreno 已提交
198 199 200 201 202 203
			const listFocus = list.getFocus();
			if (listFocus.length) {
				list.reveal(listFocus[0]);
			}
		}

204 205 206 207 208
		// Tree
		else if (focused) {
			const tree = focused;

			tree.focusPrevious(count, { origin: 'keyboard' });
209
			tree.reveal(tree.getFocus());
210 211 212
		}
	}

213
	KeybindingsRegistry.registerCommandAndKeybindingRule({
B
Benjamin Pasero 已提交
214
		id: 'list.focusUp',
215
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
216
		when: WorkbenchListFocusContextKey,
217 218 219 220 221
		primary: KeyCode.UpArrow,
		mac: {
			primary: KeyCode.UpArrow,
			secondary: [KeyMod.WinCtrl | KeyCode.KEY_P]
		},
222 223 224 225 226
		handler: (accessor, arg2) => focusUp(accessor, arg2)
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.expandSelectionUp',
227
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
228
		when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
229
		primary: KeyMod.Shift | KeyCode.UpArrow,
230
		handler: (accessor, arg2) => {
J
Joao Moreno 已提交
231
			const focused = accessor.get(IListService).lastFocusedList;
232 233

			// List
J
Joao Moreno 已提交
234
			if (focused instanceof List || focused instanceof PagedList) {
235 236
				const list = focused;

237 238 239 240 241 242
				// Focus up first
				const previousFocus = list.getFocus() ? list.getFocus()[0] : void 0;
				focusUp(accessor, arg2);

				// Then adjust selection
				expandMultiSelection(focused, previousFocus);
243 244 245 246 247 248
			}

			// Tree
			else if (focused) {
				const tree = focused;

249 250 251 252 253 254
				// Focus up first
				const previousFocus = tree.getFocus();
				focusUp(accessor, arg2);

				// Then adjust selection
				expandMultiSelection(focused, previousFocus);
255 256 257 258 259
			}
		}
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
260
		id: 'list.collapse',
261
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
262
		when: WorkbenchListFocusContextKey,
263 264 265 266 267 268
		primary: KeyCode.LeftArrow,
		mac: {
			primary: KeyCode.LeftArrow,
			secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow]
		},
		handler: (accessor) => {
J
Joao Moreno 已提交
269
			const focused = accessor.get(IListService).lastFocusedList;
270 271

			// Tree only
J
Joao Moreno 已提交
272
			if (focused && !(focused instanceof List || focused instanceof PagedList)) {
J
Joao Moreno 已提交
273
				if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
274 275 276 277 278 279
					const tree = focused;
					const focusedElements = tree.getFocus();

					if (focusedElements.length === 0) {
						return;
					}
280

J
Joao Moreno 已提交
281
					const focus = focusedElements[0];
282

J
Joao Moreno 已提交
283 284 285 286
					if (!tree.collapse(focus)) {
						const parent = tree.getParentElement(focus);

						if (parent) {
287 288
							const fakeKeyboardEvent = new KeyboardEvent('keydown');
							tree.setFocus([parent], fakeKeyboardEvent);
J
Joao Moreno 已提交
289 290
							tree.reveal(parent);
						}
291
					}
J
Joao Moreno 已提交
292 293 294 295 296 297 298 299 300 301
				} else {
					const tree = focused;
					const focus = tree.getFocus();

					tree.collapse(focus).then(didCollapse => {
						if (focus && !didCollapse) {
							tree.focusParent({ origin: 'keyboard' });

							return tree.reveal(tree.getFocus());
						}
302

J
Joao Moreno 已提交
303 304 305
						return void 0;
					});
				}
306 307 308 309 310
			}
		}
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
311
		id: 'list.expand',
312
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
313
		when: WorkbenchListFocusContextKey,
314 315
		primary: KeyCode.RightArrow,
		handler: (accessor) => {
J
Joao Moreno 已提交
316
			const focused = accessor.get(IListService).lastFocusedList;
317 318

			// Tree only
J
Joao Moreno 已提交
319
			if (focused && !(focused instanceof List || focused instanceof PagedList)) {
J
Joao Moreno 已提交
320
				if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
321 322 323 324 325 326 327 328
					const tree = focused;
					const focusedElements = tree.getFocus();

					if (focusedElements.length === 0) {
						return;
					}

					const focus = focusedElements[0];
329

J
Joao Moreno 已提交
330 331
					if (!tree.expand(focus)) {
						const child = tree.getFirstElementChild(focus);
332

J
Joao Moreno 已提交
333
						if (child) {
334 335
							const fakeKeyboardEvent = new KeyboardEvent('keydown');
							tree.setFocus([child], fakeKeyboardEvent);
J
Joao Moreno 已提交
336 337
							tree.reveal(child);
						}
338
					}
J
Joao Moreno 已提交
339 340 341
				} else {
					const tree = focused;
					const focus = tree.getFocus();
342

J
Joao Moreno 已提交
343 344 345 346 347 348 349 350 351 352
					tree.expand(focus).then(didExpand => {
						if (focus && !didExpand) {
							tree.focusFirstChild({ origin: 'keyboard' });

							return tree.reveal(tree.getFocus());
						}

						return void 0;
					});
				}
353 354 355
			}
		}
	});
356 357

	KeybindingsRegistry.registerCommandAndKeybindingRule({
B
Benjamin Pasero 已提交
358
		id: 'list.focusPageUp',
359
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
360
		when: WorkbenchListFocusContextKey,
361 362
		primary: KeyCode.PageUp,
		handler: (accessor) => {
J
Joao Moreno 已提交
363
			const focused = accessor.get(IListService).lastFocusedList;
364

365 366 367
			// Ensure DOM Focus
			ensureDOMFocus(focused);

368
			// List
J
Joao Moreno 已提交
369
			if (focused instanceof List || focused instanceof PagedList) {
370 371 372 373 374 375
				const list = focused;

				list.focusPreviousPage();
				list.reveal(list.getFocus()[0]);
			}

J
Joao Moreno 已提交
376
			// ObjectTree
J
Joao Moreno 已提交
377
			else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
378 379
				const list = focused;

380 381
				const fakeKeyboardEvent = new KeyboardEvent('keydown');
				list.focusPreviousPage(fakeKeyboardEvent);
J
Joao Moreno 已提交
382 383 384
				list.reveal(list.getFocus()[0]);
			}

385 386 387 388 389
			// Tree
			else if (focused) {
				const tree = focused;

				tree.focusPreviousPage({ origin: 'keyboard' });
390
				tree.reveal(tree.getFocus());
391 392 393 394 395
			}
		}
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
B
Benjamin Pasero 已提交
396
		id: 'list.focusPageDown',
397
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
398
		when: WorkbenchListFocusContextKey,
399 400
		primary: KeyCode.PageDown,
		handler: (accessor) => {
J
Joao Moreno 已提交
401
			const focused = accessor.get(IListService).lastFocusedList;
402

403 404 405
			// Ensure DOM Focus
			ensureDOMFocus(focused);

406
			// List
J
Joao Moreno 已提交
407
			if (focused instanceof List || focused instanceof PagedList) {
408 409 410 411 412 413
				const list = focused;

				list.focusNextPage();
				list.reveal(list.getFocus()[0]);
			}

J
Joao Moreno 已提交
414
			// ObjectTree
J
Joao Moreno 已提交
415
			else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
416 417
				const list = focused;

418 419
				const fakeKeyboardEvent = new KeyboardEvent('keydown');
				list.focusNextPage(fakeKeyboardEvent);
J
Joao Moreno 已提交
420 421 422
				list.reveal(list.getFocus()[0]);
			}

423 424 425 426 427
			// Tree
			else if (focused) {
				const tree = focused;

				tree.focusNextPage({ origin: 'keyboard' });
428
				tree.reveal(tree.getFocus());
429 430 431 432 433
			}
		}
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
B
Benjamin Pasero 已提交
434
		id: 'list.focusFirst',
435
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
436
		when: WorkbenchListFocusContextKey,
437
		primary: KeyCode.Home,
438 439
		handler: accessor => listFocusFirst(accessor)
	});
440

441 442
	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.focusFirstChild',
443
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
444
		when: WorkbenchListFocusContextKey,
A
Alex Dima 已提交
445
		primary: 0,
446 447
		handler: accessor => listFocusFirst(accessor, { fromFocused: true })
	});
B
Benjamin Pasero 已提交
448

449
	function listFocusFirst(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void {
J
Joao Moreno 已提交
450
		const focused = accessor.get(IListService).lastFocusedList;
B
Benjamin Pasero 已提交
451

452 453 454
		// Ensure DOM Focus
		ensureDOMFocus(focused);

455
		// List
J
Joao Moreno 已提交
456
		if (focused instanceof List || focused instanceof PagedList) {
457
			const list = focused;
458

459 460
			list.setFocus([0]);
			list.reveal(0);
461
		}
462

J
Joao Moreno 已提交
463
		// ObjectTree
J
Joao Moreno 已提交
464
		else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
465
			const list = focused;
J
Joao Moreno 已提交
466
			const first = list.getFirstElementChild(null);
J
Joao Moreno 已提交
467

J
Joao Moreno 已提交
468 469 470 471
			if (!first) {
				return;
			}

472 473
			const fakeKeyboardEvent = new KeyboardEvent('keydown');
			list.setFocus([first], fakeKeyboardEvent);
J
Joao Moreno 已提交
474
			list.reveal(first);
J
Joao Moreno 已提交
475 476
		}

477 478 479 480 481
		// Tree
		else if (focused) {
			const tree = focused;

			tree.focusFirst({ origin: 'keyboard' }, options && options.fromFocused ? tree.getFocus() : void 0);
482
			tree.reveal(tree.getFocus());
483 484
		}
	}
485 486

	KeybindingsRegistry.registerCommandAndKeybindingRule({
B
Benjamin Pasero 已提交
487
		id: 'list.focusLast',
488
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
489
		when: WorkbenchListFocusContextKey,
490
		primary: KeyCode.End,
491 492
		handler: accessor => listFocusLast(accessor)
	});
493

494 495
	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.focusLastChild',
496
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
497
		when: WorkbenchListFocusContextKey,
A
Alex Dima 已提交
498
		primary: 0,
499 500
		handler: accessor => listFocusLast(accessor, { fromFocused: true })
	});
B
Benjamin Pasero 已提交
501

502
	function listFocusLast(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void {
J
Joao Moreno 已提交
503
		const focused = accessor.get(IListService).lastFocusedList;
B
Benjamin Pasero 已提交
504

505 506 507
		// Ensure DOM Focus
		ensureDOMFocus(focused);

508
		// List
J
Joao Moreno 已提交
509
		if (focused instanceof List || focused instanceof PagedList) {
510
			const list = focused;
511

512 513
			list.setFocus([list.length - 1]);
			list.reveal(list.length - 1);
514
		}
515

J
Joao Moreno 已提交
516
		// ObjectTree
J
Joao Moreno 已提交
517
		else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
518 519 520 521 522 523 524
			const list = focused;
			const last = list.getLastElementAncestor();

			if (!last) {
				return;
			}

525 526
			const fakeKeyboardEvent = new KeyboardEvent('keydown');
			list.setFocus([last], fakeKeyboardEvent);
J
Joao Moreno 已提交
527 528 529
			list.reveal(last);
		}

530 531 532 533 534
		// Tree
		else if (focused) {
			const tree = focused;

			tree.focusLast({ origin: 'keyboard' }, options && options.fromFocused ? tree.getFocus() : void 0);
535
			tree.reveal(tree.getFocus());
536 537
		}
	}
538 539 540

	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.select',
541
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
542
		when: WorkbenchListFocusContextKey,
543
		primary: KeyCode.Enter,
544 545
		mac: {
			primary: KeyCode.Enter,
546
			secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow]
547
		},
548
		handler: (accessor) => {
J
Joao Moreno 已提交
549
			const focused = accessor.get(IListService).lastFocusedList;
550 551

			// List
J
Joao Moreno 已提交
552
			if (focused instanceof List || focused instanceof PagedList) {
553
				const list = focused;
J
Joao Moreno 已提交
554
				list.setSelection(list.getFocus());
J
Joao Moreno 已提交
555
				list.open(list.getFocus());
556 557
			}

J
Joao Moreno 已提交
558
			// ObjectTree
J
Joao Moreno 已提交
559
			else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
560
				const list = focused;
561 562
				const fakeKeyboardEvent = new KeyboardEvent('keydown');
				list.setSelection(list.getFocus(), fakeKeyboardEvent);
J
Joao Moreno 已提交
563 564 565
				list.open(list.getFocus());
			}

566 567 568 569 570 571 572 573 574 575 576 577
			// Tree
			else if (focused) {
				const tree = focused;
				const focus = tree.getFocus();

				if (focus) {
					tree.setSelection([focus], { origin: 'keyboard' });
				}
			}
		}
	});

J
Joao Moreno 已提交
578 579
	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.selectAll',
580
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
581
		when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
J
Joao Moreno 已提交
582 583 584 585 586 587 588 589 590 591 592 593
		primary: KeyMod.CtrlCmd | KeyCode.KEY_A,
		handler: (accessor) => {
			const focused = accessor.get(IListService).lastFocusedList;

			// List
			if (focused instanceof List || focused instanceof PagedList) {
				const list = focused;
				list.setSelection(range(list.length));
			}
		}
	});

594 595
	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.toggleExpand',
596
		weight: KeybindingWeight.WorkbenchContrib,
J
Joao Moreno 已提交
597
		when: WorkbenchListFocusContextKey,
598 599
		primary: KeyCode.Space,
		handler: (accessor) => {
J
Joao Moreno 已提交
600
			const focused = accessor.get(IListService).lastFocusedList;
601 602

			// Tree only
J
Joao Moreno 已提交
603
			if (focused && !(focused instanceof List || focused instanceof PagedList)) {
J
Joao Moreno 已提交
604
				if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
605 606
					const tree = focused;
					const focus = tree.getFocus();
607

J
Joao Moreno 已提交
608 609 610 611
					if (focus.length === 0) {
						return;
					}

J
Joao Moreno 已提交
612
					tree.toggleCollapsed(focus[0]);
J
Joao Moreno 已提交
613 614 615 616 617 618 619
				} else {
					const tree = focused;
					const focus = tree.getFocus();

					if (focus) {
						tree.toggleExpansion(focus);
					}
620 621 622 623 624 625 626
				}
			}
		}
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'list.clear',
627
		weight: KeybindingWeight.WorkbenchContrib,
628
		when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListHasSelectionOrFocus),
629 630
		primary: KeyCode.Escape,
		handler: (accessor) => {
J
Joao Moreno 已提交
631
			const focused = accessor.get(IListService).lastFocusedList;
632

633 634 635 636 637 638
			// List
			if (focused instanceof List || focused instanceof PagedList) {
				const list = focused;

				if (list.getSelection().length > 0) {
					list.setSelection([]);
J
Joao Moreno 已提交
639 640
				} else if (list.getFocus().length > 0) {
					list.setFocus([]);
641
				}
J
Joao Moreno 已提交
642
			}
643

J
Joao Moreno 已提交
644
			// ObjectTree
J
Joao Moreno 已提交
645
			else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
J
Joao Moreno 已提交
646
				const list = focused;
647
				const fakeKeyboardEvent = new KeyboardEvent('keydown');
648

J
Joao Moreno 已提交
649
				if (list.getSelection().length > 0) {
650
					list.setSelection([], fakeKeyboardEvent);
J
Joao Moreno 已提交
651
				} else if (list.getFocus().length > 0) {
652
					list.setFocus([], fakeKeyboardEvent);
653 654 655 656 657
				}
			}

			// Tree
			else if (focused) {
658 659 660 661
				const tree = focused;

				if (tree.getSelection().length) {
					tree.clearSelection({ origin: 'keyboard' });
J
Joao Moreno 已提交
662
				} else if (tree.getFocus()) {
663 664 665 666 667
					tree.clearFocus({ origin: 'keyboard' });
				}
			}
		}
	});
668 669 670 671 672

	// --- commands

	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'workbench.action.closeWindow', // close the window when the last editor is closed by reusing the same keybinding
673
		weight: KeybindingWeight.WorkbenchContrib,
B
Benjamin Pasero 已提交
674
		when: ContextKeyExpr.and(NoEditorsVisibleContext, SingleEditorGroupsContext),
675 676
		primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
		handler: accessor => {
677 678
			const windowService = accessor.get(IWindowService);
			windowService.closeWindow();
679 680 681 682 683
		}
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
		id: 'workbench.action.exitZenMode',
684
		weight: KeybindingWeight.EditorContrib - 1000,
685 686 687 688
		handler(accessor: ServicesAccessor, configurationOrName: any) {
			const partService = accessor.get(IPartService);
			partService.toggleZenMode();
		},
689
		when: InEditorZenModeContext,
690 691 692 693
		primary: KeyChord(KeyCode.Escape, KeyCode.Escape)
	});

	KeybindingsRegistry.registerCommandAndKeybindingRule({
I
isidor 已提交
694
		id: QUIT_ID,
695
		weight: KeybindingWeight.WorkbenchContrib,
696 697 698 699 700 701 702 703 704
		handler(accessor: ServicesAccessor) {
			const windowsService = accessor.get(IWindowsService);
			windowsService.quit();
		},
		when: void 0,
		primary: KeyMod.CtrlCmd | KeyCode.KEY_Q,
		win: { primary: void 0 }
	});

705
	CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, path: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string) {
706 707
		const windowsService = accessor.get(IWindowsService);

708
		return windowsService.removeFromRecentlyOpened([path]).then(() => void 0);
709
	});
S
Sandeep Somavarapu 已提交
710

S
Sandeep Somavarapu 已提交
711
	CommandsRegistry.registerCommand('_workbench.downloadResource', function (accessor: ServicesAccessor, resource: URI) {
S
Sandeep Somavarapu 已提交
712
		const downloadService = accessor.get(IDownloadService);
713
		const location = posix.join(tmpdir(), generateUuid());
S
Sandeep Somavarapu 已提交
714

S
Sandeep Somavarapu 已提交
715
		return downloadService.download(resource, location).then(() => URI.file(location));
S
Sandeep Somavarapu 已提交
716
	});
717
}