Skip to content

Commit 5e8b680

Browse files
Command Center With Help (microsoft#163635)
* Command Center With Modes * fix bug
1 parent ac9aff3 commit 5e8b680

File tree

7 files changed

+185
-52
lines changed

7 files changed

+185
-52
lines changed

src/vs/platform/quickinput/browser/helpQuickAccess.ts

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { localize } from 'vs/nls';
77
import { Registry } from 'vs/platform/registry/common/platform';
88
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
99
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
10-
import { Extensions, IQuickAccessProvider, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
10+
import { Extensions, IQuickAccessProvider, IQuickAccessProviderDescriptor, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
1111
import { IQuickInputService, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
1212

1313
interface IHelpQuickAccessPickItem extends IQuickPickItem {
@@ -46,34 +46,33 @@ export class HelpQuickAccessProvider implements IQuickAccessProvider {
4646
}));
4747

4848
// Fill in all providers
49-
picker.items = this.getQuickAccessProviders();
49+
picker.items = this.getQuickAccessProviders().filter(p => p.prefix !== HelpQuickAccessProvider.PREFIX);
5050

5151
return disposables;
5252
}
5353

54-
private getQuickAccessProviders(): IHelpQuickAccessPickItem[] {
55-
const providers: IHelpQuickAccessPickItem[] = [];
56-
57-
for (const provider of this.registry.getQuickAccessProviders().sort((providerA, providerB) => providerA.prefix.localeCompare(providerB.prefix))) {
58-
if (provider.prefix === HelpQuickAccessProvider.PREFIX) {
59-
continue; // exclude help which is already active
60-
}
61-
62-
for (const helpEntry of provider.helpEntries) {
63-
const prefix = helpEntry.prefix || provider.prefix;
64-
const label = prefix || '\u2026' /* ... */;
65-
66-
providers.push({
67-
prefix,
68-
label,
69-
keybinding: helpEntry.commandId ? this.keybindingService.lookupKeybinding(helpEntry.commandId) : undefined,
70-
ariaLabel: localize('helpPickAriaLabel', "{0}, {1}", label, helpEntry.description),
71-
description: helpEntry.description
72-
});
73-
}
74-
}
54+
public getQuickAccessProviders(): IHelpQuickAccessPickItem[] {
55+
const providers: IHelpQuickAccessPickItem[] = this.registry
56+
.getQuickAccessProviders()
57+
.sort((providerA, providerB) => providerA.prefix.localeCompare(providerB.prefix))
58+
.flatMap(provider => this.createPicks(provider));
7559

7660
return providers;
7761
}
62+
63+
private createPicks(provider: IQuickAccessProviderDescriptor): IHelpQuickAccessPickItem[] {
64+
return provider.helpEntries.map(helpEntry => {
65+
const prefix = helpEntry.prefix || provider.prefix;
66+
const label = prefix || '\u2026' /* ... */;
67+
68+
return {
69+
prefix,
70+
label,
71+
keybinding: helpEntry.commandId ? this.keybindingService.lookupKeybinding(helpEntry.commandId) : undefined,
72+
ariaLabel: localize('helpPickAriaLabel', "{0}, {1}", label, helpEntry.description),
73+
description: helpEntry.description
74+
};
75+
});
76+
}
7877
}
7978

src/vs/platform/quickinput/browser/pickerQuickAccess.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { timeout } from 'vs/base/common/async';
77
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
88
import { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
99
import { IKeyMods, IQuickPickDidAcceptEvent, IQuickPickSeparator } from 'vs/base/parts/quickinput/common/quickInput';
10-
import { IQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess';
10+
import { IQuickAccessProvider, IQuickAccessProviderRunOptions } from 'vs/platform/quickinput/common/quickAccess';
1111
import { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
1212

1313
export enum TriggerAction {
@@ -97,7 +97,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
9797
super();
9898
}
9999

100-
provide(picker: IQuickPick<T>, token: CancellationToken): IDisposable {
100+
provide(picker: IQuickPick<T>, token: CancellationToken, runOptions?: IQuickAccessProviderRunOptions): IDisposable {
101101
const disposables = new DisposableStore();
102102

103103
// Apply options if any
@@ -122,7 +122,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
122122
// Collect picks and support both long running and short or combined
123123
const picksToken = picksCts.token;
124124
const picksFilter = picker.value.substr(this.prefix.length).trim();
125-
const providedPicks = this._getPicks(picksFilter, picksDisposables, picksToken);
125+
const providedPicks = this._getPicks(picksFilter, picksDisposables, picksToken, runOptions);
126126

127127
const applyPicks = (picks: Picks<T>, skipEmpty?: boolean): boolean => {
128128
let items: readonly Pick<T>[];
@@ -338,5 +338,5 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
338338
* @returns the picks either directly, as promise or combined fast and slow results.
339339
* Pickers can return `null` to signal that no change in picks is needed.
340340
*/
341-
protected abstract _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Picks<T> | Promise<Picks<T>> | FastAndSlowPicks<T> | null;
341+
protected abstract _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken, runOptions?: IQuickAccessProviderRunOptions): Picks<T> | Promise<Picks<T>> | FastAndSlowPicks<T> | null;
342342
}

src/vs/platform/quickinput/browser/quickAccess.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
88
import { once } from 'vs/base/common/functional';
99
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
1010
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
11-
import { DefaultQuickAccessFilterValue, Extensions, IQuickAccessController, IQuickAccessOptions, IQuickAccessProvider, IQuickAccessProviderDescriptor, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
11+
import { DefaultQuickAccessFilterValue, Extensions, IQuickAccessController, IQuickAccessOptions, IQuickAccessProvider, IQuickAccessProviderDescriptor, IQuickAccessProviderRunOptions, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
1212
import { IQuickInputService, IQuickPick, IQuickPickItem, ItemActivation } from 'vs/platform/quickinput/common/quickInput';
1313
import { Registry } from 'vs/platform/registry/common/platform';
1414

@@ -122,14 +122,14 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon
122122
}
123123

124124
// Register listeners
125-
disposables.add(this.registerPickerListeners(picker, provider, descriptor, value));
125+
disposables.add(this.registerPickerListeners(picker, provider, descriptor, value, options?.providerOptions));
126126

127127
// Ask provider to fill the picker as needed if we have one
128128
// and pass over a cancellation token that will indicate when
129129
// the picker is hiding without a pick being made.
130130
const cts = disposables.add(new CancellationTokenSource());
131131
if (provider) {
132-
disposables.add(provider.provide(picker, cts.token));
132+
disposables.add(provider.provide(picker, cts.token, options?.providerOptions));
133133
}
134134

135135
// Finally, trigger disposal and cancellation when the picker
@@ -173,7 +173,13 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon
173173
picker.valueSelection = valueSelection;
174174
}
175175

176-
private registerPickerListeners(picker: IQuickPick<IQuickPickItem>, provider: IQuickAccessProvider | undefined, descriptor: IQuickAccessProviderDescriptor | undefined, value: string): IDisposable {
176+
private registerPickerListeners(
177+
picker: IQuickPick<IQuickPickItem>,
178+
provider: IQuickAccessProvider | undefined,
179+
descriptor: IQuickAccessProviderDescriptor | undefined,
180+
value: string,
181+
providerOptions?: IQuickAccessProviderRunOptions
182+
): IDisposable {
177183
const disposables = new DisposableStore();
178184

179185
// Remember as last visible picker and clean up once picker get's disposed
@@ -189,7 +195,12 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon
189195
disposables.add(picker.onDidChangeValue(value => {
190196
const [providerForValue] = this.getOrInstantiateProvider(value);
191197
if (providerForValue !== provider) {
192-
this.show(value, { preserveValue: true } /* do not rewrite value from user typing! */);
198+
this.show(value, {
199+
// do not rewrite value from user typing!
200+
preserveValue: true,
201+
// persist the value of the providerOptions from the original showing
202+
providerOptions: providerOptions
203+
});
193204
} else {
194205
visibleQuickAccess.value = value; // remember the value in our visible one
195206
}

src/vs/platform/quickinput/common/quickAccess.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ import { ItemActivation } from 'vs/base/parts/quickinput/common/quickInput';
1010
import { IQuickNavigateConfiguration, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
1111
import { Registry } from 'vs/platform/registry/common/platform';
1212

13+
/**
14+
* Provider specific options for this particular showing of the
15+
* quick access.
16+
*/
17+
export interface IQuickAccessProviderRunOptions { }
18+
19+
/**
20+
* The specific options for the AnythingQuickAccessProvider. Put here to share between layers.
21+
*/
22+
export interface AnythingQuickAccessProviderRunOptions extends IQuickAccessProviderRunOptions {
23+
includeHelp?: boolean;
24+
}
25+
1326
export interface IQuickAccessOptions {
1427

1528
/**
@@ -28,6 +41,12 @@ export interface IQuickAccessOptions {
2841
* from any existing value if quick access is visible.
2942
*/
3043
preserveValue?: boolean;
44+
45+
/**
46+
* Provider specific options for this particular showing of the
47+
* quick access.
48+
*/
49+
providerOptions?: IQuickAccessProviderRunOptions;
3150
}
3251

3352
export interface IQuickAccessController {
@@ -80,10 +99,12 @@ export interface IQuickAccessProvider {
8099
* a long running operation or from event handlers because it could be that the
81100
* picker has been closed or changed meanwhile. The token can be used to find out
82101
* that the picker was closed without picking an entry (e.g. was canceled by the user).
102+
* @param options additional configuration specific for this provider that will
103+
* influence what picks will be shown.
83104
* @return a disposable that will automatically be disposed when the picker
84105
* closes or is replaced by another picker.
85106
*/
86-
provide(picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable;
107+
provide(picker: IQuickPick<IQuickPickItem>, token: CancellationToken, options?: IQuickAccessProviderRunOptions): IDisposable;
87108
}
88109

89110
export interface IQuickAccessProviderHelp {

src/vs/workbench/browser/actions/quickAccessActions.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
1313
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
1414
import { inQuickPickContext, defaultQuickAccessContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
1515
import { ILocalizedString } from 'vs/platform/action/common/action';
16+
import { AnythingQuickAccessProviderRunOptions } from 'vs/platform/quickinput/common/quickAccess';
1617

1718
//#region Quick access management commands and keys
1819

@@ -139,6 +140,24 @@ registerAction2(class QuickAccessAction extends Action2 {
139140
secondary: globalQuickAccessKeybinding.secondary,
140141
mac: globalQuickAccessKeybinding.mac
141142
},
143+
f1: true
144+
});
145+
}
146+
147+
run(accessor: ServicesAccessor, prefix: undefined): void {
148+
const quickInputService = accessor.get(IQuickInputService);
149+
quickInputService.quickAccess.show(typeof prefix === 'string' ? prefix : undefined, { preserveValue: typeof prefix === 'string' /* preserve as is if provided */ });
150+
}
151+
});
152+
153+
registerAction2(class QuickAccessAction extends Action2 {
154+
constructor() {
155+
super({
156+
id: 'workbench.action.quickOpenWithModes',
157+
title: {
158+
value: localize('quickOpenWithModes', "Launch Command Center"),
159+
original: 'Launch Command Center'
160+
},
142161
f1: true,
143162
menu: {
144163
id: MenuId.CommandCenter,
@@ -147,9 +166,13 @@ registerAction2(class QuickAccessAction extends Action2 {
147166
});
148167
}
149168

150-
run(accessor: ServicesAccessor, prefix: undefined): void {
169+
run(accessor: ServicesAccessor): void {
151170
const quickInputService = accessor.get(IQuickInputService);
152-
quickInputService.quickAccess.show(typeof prefix === 'string' ? prefix : undefined, { preserveValue: typeof prefix === 'string' /* preserve as is if provided */ });
171+
quickInputService.quickAccess.show(undefined, {
172+
providerOptions: {
173+
includeHelp: true,
174+
} as AnythingQuickAccessProviderRunOptions
175+
});
153176
}
154177
});
155178

src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class CommandCenterControl {
5050
telemetrySource: 'commandCenter',
5151
actionViewItemProvider: (action) => {
5252

53-
if (action instanceof MenuItemAction && action.id === 'workbench.action.quickOpen') {
53+
if (action instanceof MenuItemAction && action.id === 'workbench.action.quickOpenWithModes') {
5454

5555
class CommandCenterViewItem extends BaseActionViewItem {
5656

0 commit comments

Comments
 (0)