From fadfa54300b4b0026a2347cf537cd77ee162970e Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Fri, 27 Mar 2020 10:16:42 +0100 Subject: [PATCH] Use new task quick pick in quick access Part of #90087 --- .../contrib/tasks/browser/taskQuickPick.ts | 44 +++--- .../contrib/tasks/browser/tasksQuickAccess.ts | 136 ++++++------------ 2 files changed, 68 insertions(+), 112 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts index 45d8e6a9ea2..5554b63cd18 100644 --- a/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts +++ b/src/vs/workbench/contrib/tasks/browser/taskQuickPick.ts @@ -33,7 +33,8 @@ const SHOW_ALL: string = nls.localize('taskQuickPick.showAll', "Show All Tasks.. export class TaskQuickPick extends Disposable { private sorter: TaskSorter; - private constructor( + private topLevelEntries: QuickPickInput[] | undefined; + constructor( private taskService: ITaskService, private configurationService: IConfigurationService, private quickInputService: IQuickInputService) { @@ -118,33 +119,36 @@ export class TaskQuickPick extends Disposable { return dedupedConfiguredTasks; } - private async createTopLevelEntries(defaultEntry?: TaskQuickPickEntry): Promise<{ entries: QuickPickInput[], isSingleConfigured?: Task | ConfiguringTask }> { + public async getTopLevelEntries(defaultEntry?: TaskQuickPickEntry): Promise<{ entries: QuickPickInput[], isSingleConfigured?: Task | ConfiguringTask }> { + if (this.topLevelEntries !== undefined) { + return { entries: this.topLevelEntries }; + } const recentTasks: (Task | ConfiguringTask)[] = (await this.taskService.readRecentTasks()).reverse(); const configuredTasks: (Task | ConfiguringTask)[] = this.handleFolderTaskResult(await this.taskService.getWorkspaceTasks()); const extensionTaskTypes = this.taskService.taskTypes(); - const taskQuickPickEntries: QuickPickInput[] = []; + this.topLevelEntries = []; if (recentTasks.length > 0) { - this.createEntriesForGroup(taskQuickPickEntries, recentTasks, nls.localize('recentlyUsed', 'recently used')); + this.createEntriesForGroup(this.topLevelEntries, recentTasks, nls.localize('recentlyUsed', 'recently used')); } if (configuredTasks.length > 0) { let dedupedConfiguredTasks: (Task | ConfiguringTask)[] = this.dedupeConfiguredAndRecent(recentTasks, configuredTasks); if (dedupedConfiguredTasks.length > 0) { - this.createEntriesForGroup(taskQuickPickEntries, dedupedConfiguredTasks, nls.localize('configured', 'configured')); + this.createEntriesForGroup(this.topLevelEntries, dedupedConfiguredTasks, nls.localize('configured', 'configured')); } } if (defaultEntry && (configuredTasks.length === 0)) { - taskQuickPickEntries.push({ type: 'separator', label: nls.localize('configured', 'configured') }); - taskQuickPickEntries.push(defaultEntry); + this.topLevelEntries.push({ type: 'separator', label: nls.localize('configured', 'configured') }); + this.topLevelEntries.push(defaultEntry); } if (extensionTaskTypes.length > 0) { - this.createTypeEntries(taskQuickPickEntries, extensionTaskTypes); + this.createTypeEntries(this.topLevelEntries, extensionTaskTypes); } - return { entries: taskQuickPickEntries, isSingleConfigured: configuredTasks.length === 1 ? configuredTasks[0] : undefined }; + return { entries: this.topLevelEntries, isSingleConfigured: configuredTasks.length === 1 ? configuredTasks[0] : undefined }; } - private async show(placeHolder: string, defaultEntry?: TaskQuickPickEntry): Promise { + public async show(placeHolder: string, defaultEntry?: TaskQuickPickEntry, startAtType?: string): Promise { const picker: IQuickPick = this.quickInputService.createQuickPick(); picker.placeholder = placeHolder; picker.matchOnDescription = true; @@ -161,22 +165,24 @@ export class TaskQuickPick extends Disposable { } }); - // First show recent tasks configured tasks. Other tasks will be available at a second level - const topLevelEntriesResult = await this.createTopLevelEntries(defaultEntry); - if (topLevelEntriesResult.isSingleConfigured && this.configurationService.getValue(QUICKOPEN_SKIP_CONFIG)) { - picker.dispose(); - return this.toTask(topLevelEntriesResult.isSingleConfigured); + let firstLevelTask: Task | ConfiguringTask | string | undefined | null = startAtType; + if (!firstLevelTask) { + // First show recent tasks configured tasks. Other tasks will be available at a second level + const topLevelEntriesResult = await this.getTopLevelEntries(defaultEntry); + if (topLevelEntriesResult.isSingleConfigured && this.configurationService.getValue(QUICKOPEN_SKIP_CONFIG)) { + picker.dispose(); + return this.toTask(topLevelEntriesResult.isSingleConfigured); + } + const taskQuickPickEntries: QuickPickInput[] = topLevelEntriesResult.entries; + firstLevelTask = await this.doPickerFirstLevel(picker, taskQuickPickEntries); } - const taskQuickPickEntries: QuickPickInput[] = topLevelEntriesResult.entries; - do { - const firstLevelTask = await this.doPickerFirstLevel(picker, taskQuickPickEntries); if (Types.isString(firstLevelTask)) { // Proceed to second level of quick pick const selectedEntry = await this.doPickerSecondLevel(picker, firstLevelTask); if (selectedEntry && selectedEntry.task === null) { // The user has chosen to go back to the first level - continue; + firstLevelTask = await this.doPickerFirstLevel(picker, (await this.getTopLevelEntries(defaultEntry)).entries); } else { picker.dispose(); return (selectedEntry?.task && !Types.isString(selectedEntry?.task)) ? this.toTask(selectedEntry?.task) : undefined; diff --git a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts index 5767f8d7649..8e98f9e6e48 100644 --- a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts +++ b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickPickSeparator, IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { matchesFuzzy } from 'vs/base/common/filters'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService'; -import { CustomTask, ContributedTask } from 'vs/workbench/contrib/tasks/common/tasks'; +import { ITaskService, Task } from 'vs/workbench/contrib/tasks/common/taskService'; +import { CustomTask, ContributedTask, ConfiguringTask } from 'vs/workbench/contrib/tasks/common/tasks'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IStringDictionary } from 'vs/base/common/collections'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { TaskQuickPick, TaskTwoLevelQuickPickEntry } from 'vs/workbench/contrib/tasks/browser/taskQuickPick'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { isString } from 'vs/base/common/types'; export class TasksQuickAccessProvider extends PickerQuickAccessProvider { @@ -22,7 +24,9 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider> { - // always await extensions await this.activationPromise; @@ -38,102 +41,49 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider((task): task is CustomTask | ContributedTask => ContributedTask.is(task) || CustomTask.is(task)); - - if (token.isCancellationRequested) { - return []; - } - - this.taskService.migrateRecentTasks(tasks); + const taskQuickPick = new TaskQuickPick(this.taskService, this.configurationService, this.quickInputService); + const topLevelPicks = await taskQuickPick.getTopLevelEntries(); + const taskPicks: Array = []; - // Split up tasks across recently used, configured and detected - const recentlyUsedTasks = this.taskService.getRecentlyUsedTasks(); - const recent: Array = []; - const configured: CustomTask[] = []; - const detected: ContributedTask[] = []; - const taskMap: IStringDictionary = Object.create(null); - for (const task of tasks) { - const key = task.getRecentlyUsedKey(); - if (key) { - taskMap[key] = task; + for (const entry of topLevelPicks.entries) { + if (entry.type === 'separator') { + taskPicks.push(entry); } - } - for (const key of recentlyUsedTasks.keys()) { - const task = taskMap[key]; - if (task) { - recent.push(task); + const highlights = matchesFuzzy(filter, entry.label!, true); + if (!highlights) { + continue; } - } - for (const task of tasks) { - const key = task.getRecentlyUsedKey(); - if (!key || !recentlyUsedTasks.has(key)) { - if (CustomTask.is(task)) { - configured.push(task); + const task: Task | ConfiguringTask | string = (entry).task!; + const quickAccessEntry: IPickerQuickAccessItem = entry; + quickAccessEntry.ariaLabel = localize('entryAriaLabel', "{0}, tasks picker", entry.label!); + quickAccessEntry.highlights = { label: highlights }; + quickAccessEntry.trigger = () => { + if (ContributedTask.is(task)) { + this.taskService.customize(task, undefined, true); + } else if (CustomTask.is(task)) { + this.taskService.openConfig(task); + } + return TriggerAction.CLOSE_PICKER; + }; + quickAccessEntry.accept = async () => { + if (isString(task)) { + // switch to quick pick and show second level + taskQuickPick.show(localize('TaskService.pickRunTask', 'Select the task to run'), undefined, task); } else { - detected.push(task); + this.taskService.run(await this.toTask(task), { attachProblemMatcher: true }); } - } - } - - const taskPicks: Array = []; - const sorter = this.taskService.createSorter(); - - // Fill picks in sorted order - - this.fillPicks(taskPicks, filter, recent, localize('recentlyUsed', "recently used tasks")); - - configured.sort((a, b) => sorter.compare(a, b)); - this.fillPicks(taskPicks, filter, configured, localize('configured', "configured tasks")); - - detected.sort((a, b) => sorter.compare(a, b)); - this.fillPicks(taskPicks, filter, detected, localize('detected', "detected tasks")); + }; + taskPicks.push(quickAccessEntry); + } return taskPicks; } - private fillPicks(taskPicks: Array, input: string, tasks: Array, groupLabel: string): void { - let first = true; - for (const task of tasks) { - const highlights = matchesFuzzy(input, task._label, true); - if (!highlights) { - continue; - } - if (first) { - first = false; - taskPicks.push({ type: 'separator', label: groupLabel }); - } - taskPicks.push({ - label: task._label, - ariaLabel: localize('entryAriaLabel', "{0}, tasks picker", task._label), - description: this.taskService.getTaskDescription(task), - highlights: { label: highlights }, - buttons: (() => { - const buttons = []; - - if (ContributedTask.is(task) || CustomTask.is(task)) { - buttons.push({ - iconClass: 'codicon-gear', - tooltip: localize('customizeTask', "Configure Task") - }); - } - - return buttons; - })(), - trigger: () => { - if (ContributedTask.is(task)) { - this.taskService.customize(task, undefined, true); - } else { - this.taskService.openConfig(task); - } - - return TriggerAction.CLOSE_PICKER; - }, - accept: () => { - this.taskService.run(task, { attachProblemMatcher: true }); - } - }); + private async toTask(task: Task | ConfiguringTask): Promise { + if (!ConfiguringTask.is(task)) { + return task; } + + return this.taskService.tryResolveTask(task); } } -- GitLab