Skip to content

Commit 711c52b

Browse files
authored
Merge pull request #373 from PowerShell/daviwil/plaster-integration
Add support for new project creation using Plaster
2 parents 613dbc7 + 56fd1a7 commit 711c52b

File tree

7 files changed

+417
-109
lines changed

7 files changed

+417
-109
lines changed

examples/PromptExamples.ps1

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
# Multi-choice prompt
3+
$choices = @(
4+
New-Object "System.Management.Automation.Host.ChoiceDescription" "&Apple", "Apple"
5+
New-Object "System.Management.Automation.Host.ChoiceDescription" "&Banana", "Banana"
6+
New-Object "System.Management.Automation.Host.ChoiceDescription" "&Orange", "Orange"
7+
)
8+
9+
$defaults = [int[]]@(0, 2)
10+
$host.UI.PromptForChoice("Choose a fruit", "You may choose more than one", $choices, $defaults)

package.json

+12-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
},
2727
"main": "./out/main",
2828
"activationEvents": [
29-
"onLanguage:powershell"
29+
"onLanguage:powershell",
30+
"onCommand:PowerShell.NewProjectFromTemplate"
3031
],
3132
"dependencies": {
3233
"vscode-languageclient": "1.3.1"
@@ -128,6 +129,16 @@
128129
"command": "PowerShell.SelectPSSARules",
129130
"title": "Select PSScriptAnalyzer Rules",
130131
"category": "PowerShell"
132+
},
133+
{
134+
"command": "PowerShell.ShowSessionOutput",
135+
"title": "Show Session Output",
136+
"category": "PowerShell"
137+
},
138+
{
139+
"command": "PowerShell.NewProjectFromTemplate",
140+
"title": "Create New Project from Plaster Template",
141+
"category": "PowerShell"
131142
}
132143
],
133144
"snippets": [

src/checkboxQuickPick.ts

+84-61
Original file line numberDiff line numberDiff line change
@@ -3,74 +3,97 @@
33
*--------------------------------------------------------*/
44

55
import vscode = require("vscode");
6-
import QuickPickItem = vscode.QuickPickItem;
76

8-
export class CheckboxQuickPickItem {
9-
name: string;
7+
var confirmItemLabel: string = "$(checklist) Confirm";
8+
var checkedPrefix: string = "[ $(check) ]";
9+
var uncheckedPrefix: string = "[ ]";
10+
var defaultPlaceHolder: string = "Select 'Confirm' to confirm or press 'Esc' key to cancel";
11+
12+
export interface CheckboxQuickPickItem {
13+
label: string;
14+
description?: string;
1015
isSelected: boolean;
1116
}
1217

13-
export class CheckboxQuickPick {
14-
private static readonly confirm: string = "$(check)";
15-
private static readonly checkboxOn: string = "[ x ]";
16-
private static readonly checkboxOff: string = "[ ]";
17-
private static readonly confirmPlaceHolder: string = "Select 'Confirm' to confirm change; Press 'esc' key to cancel changes";
18-
19-
public static show(
20-
checkboxQuickPickItems: CheckboxQuickPickItem[],
21-
callback: (items: CheckboxQuickPickItem[]) => void): void {
22-
CheckboxQuickPick.showInner(checkboxQuickPickItems.slice(), callback);
23-
}
24-
25-
private static showInner(
26-
items: CheckboxQuickPickItem[],
27-
callback: (items: CheckboxQuickPickItem[]) => void): void {
18+
export interface CheckboxQuickPickOptions {
19+
confirmPlaceHolder: string;
20+
}
21+
22+
var defaultOptions:CheckboxQuickPickOptions = { confirmPlaceHolder: defaultPlaceHolder};
23+
24+
export function showCheckboxQuickPick(
25+
items: CheckboxQuickPickItem[],
26+
options: CheckboxQuickPickOptions = defaultOptions): Thenable<CheckboxQuickPickItem[]> {
27+
28+
return showInner(items, options).then(
29+
(selectedItem) => {
30+
// We're mutating the original item list so just return it for now.
31+
// If 'selectedItem' is undefined it means the user cancelled the
32+
// inner showQuickPick UI so pass the undefined along.
33+
return selectedItem != undefined ? items : undefined;
34+
})
35+
}
36+
37+
function getQuickPickItems(items: CheckboxQuickPickItem[]): vscode.QuickPickItem[] {
38+
39+
let quickPickItems: vscode.QuickPickItem[] = [];
40+
quickPickItems.push({ label: confirmItemLabel, description: "" });
41+
42+
items.forEach(item =>
43+
quickPickItems.push({
44+
label: convertToCheckBox(item),
45+
description: item.description
46+
}));
47+
48+
return quickPickItems;
49+
}
50+
51+
function showInner(
52+
items: CheckboxQuickPickItem[],
53+
options: CheckboxQuickPickOptions): Thenable<vscode.QuickPickItem> {
54+
55+
var quickPickThenable: Thenable<vscode.QuickPickItem> =
2856
vscode.window.showQuickPick(
29-
CheckboxQuickPick.getQuickPickItems(items),
57+
getQuickPickItems(items),
3058
{
3159
ignoreFocusOut: true,
3260
matchOnDescription: true,
33-
placeHolder: CheckboxQuickPick.confirmPlaceHolder
34-
}).then((selection) => {
35-
if (!selection) {
36-
return;
37-
}
38-
39-
if (selection.label === CheckboxQuickPick.confirm) {
40-
callback(items);
41-
return;
42-
}
43-
44-
let index: number = CheckboxQuickPick.getRuleIndex(items, selection.description);
45-
CheckboxQuickPick.toggleSelection(items[index]);
46-
CheckboxQuickPick.showInner(items, callback);
61+
placeHolder: options.confirmPlaceHolder
4762
});
48-
}
49-
50-
private static getRuleIndex(items: CheckboxQuickPickItem[], itemLabel: string): number {
51-
return items.findIndex(item => item.name === itemLabel);
52-
}
53-
54-
private static getQuickPickItems(items: CheckboxQuickPickItem[]): QuickPickItem[] {
55-
let quickPickItems: QuickPickItem[] = [];
56-
quickPickItems.push({ label: CheckboxQuickPick.confirm, description: "Confirm" });
57-
items.forEach(item =>
58-
quickPickItems.push({
59-
label: CheckboxQuickPick.convertToCheckBox(item.isSelected), description: item.name
60-
}));
61-
return quickPickItems;
62-
}
63-
64-
private static toggleSelection(item: CheckboxQuickPickItem): void {
65-
item.isSelected = !item.isSelected;
66-
}
67-
68-
private static convertToCheckBox(state: boolean): string {
69-
if (state) {
70-
return CheckboxQuickPick.checkboxOn;
71-
}
72-
else {
73-
return CheckboxQuickPick.checkboxOff;
74-
}
75-
}
63+
64+
return quickPickThenable.then(
65+
(selection) => {
66+
if (!selection) {
67+
//return Promise.reject<vscode.QuickPickItem>("showCheckBoxQuickPick cancelled")
68+
return Promise.resolve<vscode.QuickPickItem>(undefined);
69+
}
70+
71+
if (selection.label === confirmItemLabel) {
72+
return selection;
73+
}
74+
75+
let index: number = getItemIndex(items, selection.label);
76+
77+
if (index >= 0) {
78+
toggleSelection(items[index]);
79+
}
80+
else {
81+
console.log(`Couldn't find CheckboxQuickPickItem for label '${selection.label}'`);
82+
}
83+
84+
return showInner(items, options);
85+
});
86+
}
87+
88+
function getItemIndex(items: CheckboxQuickPickItem[], itemLabel: string): number {
89+
var trimmedLabel = itemLabel.substr(itemLabel.indexOf("]") + 2);
90+
return items.findIndex(item => item.label === trimmedLabel);
91+
}
92+
93+
function toggleSelection(item: CheckboxQuickPickItem): void {
94+
item.isSelected = !item.isSelected;
95+
}
96+
97+
function convertToCheckBox(item: CheckboxQuickPickItem): string {
98+
return `${item.isSelected ? checkedPrefix : uncheckedPrefix} ${item.label}`;
7699
}

src/features/Console.ts

+83-33
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import vscode = require('vscode');
66
import { IFeature } from '../feature';
7+
import { showCheckboxQuickPick, CheckboxQuickPickItem } from '../checkboxQuickPick'
78
import { LanguageClient, RequestType, NotificationType } from 'vscode-languageclient';
89

910
export namespace EvaluateRequest {
@@ -46,14 +47,15 @@ interface ShowInputPromptRequestArgs {
4647
}
4748

4849
interface ShowChoicePromptRequestArgs {
50+
isMultiChoice: boolean;
4951
caption: string;
5052
message: string;
5153
choices: ChoiceDetails[];
52-
defaultChoice: number;
54+
defaultChoices: number[];
5355
}
5456

5557
interface ShowChoicePromptResponseBody {
56-
chosenItem: string;
58+
responseText: string;
5759
promptCancelled: boolean;
5860
}
5961

@@ -66,36 +68,62 @@ function showChoicePrompt(
6668
promptDetails: ShowChoicePromptRequestArgs,
6769
client: LanguageClient) : Thenable<ShowChoicePromptResponseBody> {
6870

69-
var quickPickItems =
70-
promptDetails.choices.map<vscode.QuickPickItem>(choice => {
71-
return {
72-
label: choice.label,
73-
description: choice.helpMessage
74-
}
75-
});
71+
var resultThenable: Thenable<ShowChoicePromptResponseBody> = undefined;
7672

77-
// Shift the default item to the front of the
78-
// array so that the user can select it easily
79-
if (promptDetails.defaultChoice > -1 &&
80-
promptDetails.defaultChoice < promptDetails.choices.length) {
73+
if (!promptDetails.isMultiChoice) {
74+
var quickPickItems =
75+
promptDetails.choices.map<vscode.QuickPickItem>(choice => {
76+
return {
77+
label: choice.label,
78+
description: choice.helpMessage
79+
}
80+
});
8181

82-
var defaultChoiceItem = quickPickItems[promptDetails.defaultChoice];
83-
quickPickItems.splice(promptDetails.defaultChoice, 1);
82+
if (promptDetails.defaultChoices &&
83+
promptDetails.defaultChoices.length > 0) {
84+
85+
// Shift the default items to the front of the
86+
// array so that the user can select it easily
87+
var defaultChoice = promptDetails.defaultChoices[0];
88+
if (defaultChoice > -1 &&
89+
defaultChoice < promptDetails.choices.length) {
90+
91+
var defaultChoiceItem = quickPickItems[defaultChoice];
92+
quickPickItems.splice(defaultChoice, 1);
93+
94+
// Add the default choice to the head of the array
95+
quickPickItems = [defaultChoiceItem].concat(quickPickItems);
96+
}
97+
}
8498

85-
// Add the default choice to the head of the array
86-
quickPickItems = [defaultChoiceItem].concat(quickPickItems);
99+
resultThenable =
100+
vscode.window
101+
.showQuickPick(
102+
quickPickItems,
103+
{ placeHolder: promptDetails.caption + " - " + promptDetails.message })
104+
.then(onItemSelected);
87105
}
106+
else {
107+
var checkboxQuickPickItems =
108+
promptDetails.choices.map<CheckboxQuickPickItem>(choice => {
109+
return {
110+
label: choice.label,
111+
description: choice.helpMessage,
112+
isSelected: false
113+
}
114+
});
88115

89-
// For some bizarre reason, the quick pick dialog does not
90-
// work if I return the Thenable immediately at this point.
91-
// It only works if I save the thenable to a variable and
92-
// return the variable instead...
93-
var resultThenable =
94-
vscode.window
95-
.showQuickPick(
96-
quickPickItems,
97-
{ placeHolder: promptDetails.caption + " - " + promptDetails.message })
98-
.then(onItemSelected);
116+
// Select the defaults
117+
promptDetails.defaultChoices.forEach(choiceIndex => {
118+
checkboxQuickPickItems[choiceIndex].isSelected = true
119+
});
120+
121+
resultThenable =
122+
showCheckboxQuickPick(
123+
checkboxQuickPickItems,
124+
{ confirmPlaceHolder: `${promptDetails.caption} - ${promptDetails.message}`})
125+
.then(onItemsSelected);
126+
}
99127

100128
return resultThenable;
101129
}
@@ -112,18 +140,34 @@ function showInputPrompt(
112140
return resultThenable;
113141
}
114142

143+
function onItemsSelected(chosenItems: CheckboxQuickPickItem[]): ShowChoicePromptResponseBody {
144+
if (chosenItems !== undefined) {
145+
return {
146+
promptCancelled: false,
147+
responseText: chosenItems.filter(item => item.isSelected).map(item => item.label).join(", ")
148+
};
149+
}
150+
else {
151+
// User cancelled the prompt, send the cancellation
152+
return {
153+
promptCancelled: true,
154+
responseText: undefined
155+
};
156+
}
157+
}
158+
115159
function onItemSelected(chosenItem: vscode.QuickPickItem): ShowChoicePromptResponseBody {
116160
if (chosenItem !== undefined) {
117161
return {
118162
promptCancelled: false,
119-
chosenItem: chosenItem.label
163+
responseText: chosenItem.label
120164
};
121165
}
122166
else {
123167
// User cancelled the prompt, send the cancellation
124168
return {
125169
promptCancelled: true,
126-
chosenItem: undefined
170+
responseText: undefined
127171
};
128172
}
129173
}
@@ -144,12 +188,12 @@ function onInputEntered(responseText: string): ShowInputPromptResponseBody {
144188
}
145189

146190
export class ConsoleFeature implements IFeature {
147-
private command: vscode.Disposable;
191+
private commands: vscode.Disposable[];
148192
private languageClient: LanguageClient;
149193
private consoleChannel: vscode.OutputChannel;
150194

151195
constructor() {
152-
this.command =
196+
this.commands = [
153197
vscode.commands.registerCommand('PowerShell.RunSelection', () => {
154198
if (this.languageClient === undefined) {
155199
// TODO: Log error message
@@ -175,7 +219,13 @@ export class ConsoleFeature implements IFeature {
175219

176220
// Show the output window if it isn't already visible
177221
this.consoleChannel.show(vscode.ViewColumn.Three);
178-
});
222+
}),
223+
224+
vscode.commands.registerCommand('PowerShell.ShowSessionOutput', () => {
225+
// Show the output window if it isn't already visible
226+
this.consoleChannel.show(vscode.ViewColumn.Three);
227+
})
228+
];
179229

180230
this.consoleChannel = vscode.window.createOutputChannel("PowerShell Output");
181231
}
@@ -197,7 +247,7 @@ export class ConsoleFeature implements IFeature {
197247
}
198248

199249
public dispose() {
200-
this.command.dispose();
250+
this.commands.forEach(command => command.dispose());
201251
this.consoleChannel.dispose();
202252
}
203253
}

0 commit comments

Comments
 (0)