Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { IQuickPickSeparator } from '../../../../platform/quickinput/common/quickInput.js';
7
import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from '../../../../platform/quickinput/browser/pickerQuickAccess.js';
8
import { localize } from '../../../../nls.js';
9
import { INotificationService } from '../../../../platform/notification/common/notification.js';
10
import { IDebugService } from '../common/debug.js';
11
import { IWorkspaceContextService, WorkbenchState } from '../../../../platform/workspace/common/workspace.js';
12
import { ICommandService } from '../../../../platform/commands/common/commands.js';
13
import { matchesFuzzy } from '../../../../base/common/filters.js';
14
import { ADD_CONFIGURATION_ID, DEBUG_QUICK_ACCESS_PREFIX } from './debugCommands.js';
15
import { debugConfigure, debugRemoveConfig } from './debugIcons.js';
16
import { ThemeIcon } from '../../../../base/common/themables.js';
17
18
export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {
19
20
constructor(
21
@IDebugService private readonly debugService: IDebugService,
22
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
23
@ICommandService private readonly commandService: ICommandService,
24
@INotificationService private readonly notificationService: INotificationService,
25
) {
26
super(DEBUG_QUICK_ACCESS_PREFIX, {
27
noResultsPick: {
28
label: localize('noDebugResults', "No matching launch configurations")
29
}
30
});
31
}
32
33
protected async _getPicks(filter: string): Promise<(IQuickPickSeparator | IPickerQuickAccessItem)[]> {
34
const picks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];
35
if (!this.debugService.getAdapterManager().hasEnabledDebuggers()) {
36
return [];
37
}
38
39
picks.push({ type: 'separator', label: 'launch.json' });
40
41
const configManager = this.debugService.getConfigurationManager();
42
const selectedConfiguration = configManager.selectedConfiguration;
43
44
// Entries: configs
45
let lastGroup: string | undefined;
46
for (const config of configManager.getAllConfigurations()) {
47
const highlights = matchesFuzzy(filter, config.name, true);
48
if (highlights) {
49
50
const pick = {
51
label: config.name,
52
description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? config.launch.name : '',
53
highlights: { label: highlights },
54
buttons: [{
55
iconClass: ThemeIcon.asClassName(debugConfigure),
56
tooltip: localize('customizeLaunchConfig', "Configure Launch Configuration")
57
}],
58
trigger: () => {
59
config.launch.openConfigFile({ preserveFocus: false });
60
61
return TriggerAction.CLOSE_PICKER;
62
},
63
accept: async () => {
64
await configManager.selectConfiguration(config.launch, config.name);
65
try {
66
await this.debugService.startDebugging(config.launch, undefined, { startedByUser: true });
67
} catch (error) {
68
this.notificationService.error(error);
69
}
70
}
71
};
72
73
// Most recently used configuration
74
if (selectedConfiguration.name === config.name && selectedConfiguration.launch === config.launch) {
75
const separator: IQuickPickSeparator = { type: 'separator', label: localize('mostRecent', 'Most Recent') };
76
picks.unshift(separator, pick);
77
continue;
78
}
79
80
// Separator
81
if (lastGroup !== config.presentation?.group) {
82
picks.push({ type: 'separator' });
83
lastGroup = config.presentation?.group;
84
}
85
86
// Launch entry
87
88
picks.push(pick);
89
}
90
}
91
92
// Entries detected configurations
93
const dynamicProviders = await configManager.getDynamicProviders();
94
if (dynamicProviders.length > 0) {
95
picks.push({
96
type: 'separator', label: localize({
97
key: 'contributed',
98
comment: ['contributed is lower case because it looks better like that in UI. Nothing preceeds it. It is a name of the grouping of debug configurations.']
99
}, "contributed")
100
});
101
}
102
103
configManager.getRecentDynamicConfigurations().forEach(({ name, type }) => {
104
const highlights = matchesFuzzy(filter, name, true);
105
if (highlights) {
106
picks.push({
107
label: name,
108
highlights: { label: highlights },
109
buttons: [{
110
iconClass: ThemeIcon.asClassName(debugRemoveConfig),
111
tooltip: localize('removeLaunchConfig', "Remove Launch Configuration")
112
}],
113
trigger: () => {
114
configManager.removeRecentDynamicConfigurations(name, type);
115
return TriggerAction.CLOSE_PICKER;
116
},
117
accept: async () => {
118
await configManager.selectConfiguration(undefined, name, undefined, { type });
119
try {
120
const { launch, getConfig } = configManager.selectedConfiguration;
121
const config = await getConfig();
122
await this.debugService.startDebugging(launch, config, { startedByUser: true });
123
} catch (error) {
124
this.notificationService.error(error);
125
}
126
}
127
});
128
}
129
});
130
131
dynamicProviders.forEach(provider => {
132
picks.push({
133
label: `$(folder) ${provider.label}...`,
134
ariaLabel: localize({ key: 'providerAriaLabel', comment: ['Placeholder stands for the provider label. For example "NodeJS".'] }, "{0} contributed configurations", provider.label),
135
accept: async () => {
136
const pick = await provider.pick();
137
if (pick) {
138
// Use the type of the provider, not of the config since config sometimes have subtypes (for example "node-terminal")
139
await configManager.selectConfiguration(pick.launch, pick.config.name, pick.config, { type: provider.type });
140
this.debugService.startDebugging(pick.launch, pick.config, { startedByUser: true });
141
}
142
}
143
});
144
});
145
146
147
// Entries: launches
148
const visibleLaunches = configManager.getLaunches().filter(launch => !launch.hidden);
149
150
// Separator
151
if (visibleLaunches.length > 0) {
152
picks.push({ type: 'separator', label: localize('configure', "configure") });
153
}
154
155
for (const launch of visibleLaunches) {
156
const label = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ?
157
localize("addConfigTo", "Add Config ({0})...", launch.name) :
158
localize('addConfiguration', "Add Configuration...");
159
160
// Add Config entry
161
picks.push({
162
label,
163
description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? launch.name : '',
164
highlights: { label: matchesFuzzy(filter, label, true) ?? undefined },
165
accept: () => this.commandService.executeCommand(ADD_CONFIGURATION_ID, launch.uri.toString())
166
});
167
}
168
169
return picks;
170
}
171
}
172
173