Skip to content

Commit f725c92

Browse files
corbobTylerLeonhardt
authored andcommitted
Show-Command explorer v1 (#1406)
* Implement TreeView First pass at bringing a TreeView into vscode-powershell. Built currently failing on unrelated code... * Implement TreeView First pass at bringing a TreeView into vscode-powershell. Built currently failing on unrelated code... * Missed some variable names. Updated from previous name incarnation.. * Adding svg for activitybar. Require an svg for the activity bar. Taken from https://github.com/Microsoft/vscode-extension-samples/tree/master/tree-view-sample/media (MIT Licensed I think...) * Added a PowerShell SVG. Taken from gist: https://gist.github.com/Xainey/d5bde7d01dcbac51ac951810e94313aa?short_path=ec01c8c * First Attempt to call to PSES * Get data from PSES PSES isn't returning a string. Make sure we're expecting it. Allowing for console.log for debugging. These will all be removed prior to shipping. * Refactoring code * Pulling live data. Unable to currently update the list. If you run PowerShell.GetCommands prior to opening the treeview, it is populated with your commands. Need to get it to update. * WIP: Something something it's broken... * Still not refreshing. I give up for now :'( * Correct dimensions on sidebar icon Other icons appear to be 32 px square. This one was 50. Adjusting size to 32. * Minor cleanup Cleaning up the tslinter hints. Remove CommandNode, was part of a failed experiment to get the tree refresh working. * Cleanup casing and variable names. Correct casing of some things. Adjust names to increase chance of uniqueness. * Fix the refresh. Thanks to glennsarti for finding that the API expects to call back to a particular variable. * Insert Command from treeview Add Insert Command Add Right Click Options to View Reset PSES Logging to Normal Update OnlineHelp to take an item from the treeview. Pass that to online help PSES handler. * Have Command Explorer load fully on extension load. * Change to match PSES changes. Adding functionality to PSES to get all commands (Name and Module Name), or get all of a single command. This solves performance issues with getting all of all of them. * Move toCommand to be a standalone function * Remove unneccesary svg files. * Fix formatting. Remove overly verbose selection * Add some TODOs so we don't forget to do this. * Remove GetAllCommands. Refactor into a single command. If nothing is passed, it will return all objects. * Add logging when language client not defined. Clean up TODO comments Clean up request type naming. White space cleanup * Bring Treeview into using ShowHelp OnlineHelp has been deprecated as of 1.9.0. * Move anonymous functions to Named. Clean up some naming and whitespace. * Add interface for command. Eliminate any from RequestType * Eliminate another any. * Adjust casing
1 parent 7883879 commit f725c92

File tree

8 files changed

+201
-9
lines changed

8 files changed

+201
-9
lines changed

.gitattributes

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Set the default behavior, in case people don't have core.autocrlf set.
22
* text=auto
33

4+
# Set svg to binary type, as SVG is unlikely to be editted by hand. Can be treated as checked in blob
5+
*.svg binary
6+
47
# .gitattributes in project root
58
# npm now seems to be insisting on LF - see https://github.com/npm/npm/issues/17161
69
package.json text eol=lf

media/PwSh.svg

+4
Loading

package.json

+51-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"onCommand:PowerShell.SpecifyScriptArgs",
3535
"onCommand:PowerShell.ShowSessionConsole",
3636
"onCommand:PowerShell.ShowSessionMenu",
37-
"onCommand:PowerShell.RestartSession"
37+
"onCommand:PowerShell.RestartSession",
38+
"onView:PowerShellCommands"
3839
],
3940
"dependencies": {
4041
"vscode-languageclient": "~5.0.0"
@@ -58,6 +59,23 @@
5859
"test": "node ./node_modules/vscode/bin/test"
5960
},
6061
"contributes": {
62+
"viewsContainers": {
63+
"activitybar": [
64+
{
65+
"id": "PowerShellCommandExplorer",
66+
"title": "PowerShell Command Explorer",
67+
"icon": "media/pwsh.svg"
68+
}
69+
]
70+
},
71+
"views": {
72+
"PowerShellCommandExplorer": [
73+
{
74+
"id": "PowerShellCommands",
75+
"name": "PowerShell Commands"
76+
}
77+
]
78+
},
6179
"keybindings": [
6280
{
6381
"command": "PowerShell.ShowHelp",
@@ -93,6 +111,20 @@
93111
"title": "Expand Alias",
94112
"category": "PowerShell"
95113
},
114+
{
115+
"command": "PowerShell.RefreshCommandsExplorer",
116+
"title": "Refresh",
117+
"icon": {
118+
"light": "resources/light/refresh.svg",
119+
"dark": "resources/dark/refresh.svg"
120+
},
121+
"category": "PowerShell"
122+
},
123+
{
124+
"command": "PowerShell.InsertCommand",
125+
"title": "Insert Command",
126+
"category": "PowerShell"
127+
},
96128
{
97129
"command": "PowerShell.OnlineHelp",
98130
"title": "Get Online Help for Command (Deprecated)",
@@ -181,6 +213,23 @@
181213
"command": "PowerShell.ShowHelp",
182214
"group": "2_powershell"
183215
}
216+
],
217+
"view/title": [
218+
{
219+
"command": "PowerShell.RefreshCommandsExplorer",
220+
"when": "view == PowerShellCommands",
221+
"group": "navigation"
222+
}
223+
],
224+
"view/item/context": [
225+
{
226+
"command": "PowerShell.ShowHelp",
227+
"when": "view == PowerShellCommands"
228+
},
229+
{
230+
"command": "PowerShell.InsertCommand",
231+
"when": "view == PowerShellCommands"
232+
}
184233
]
185234
},
186235
"problemMatchers": [
@@ -609,4 +658,4 @@
609658
]
610659
},
611660
"private": true
612-
}
661+
}

resources/dark/refresh.svg

+1
Loading

resources/light/refresh.svg

+1
Loading

src/features/GetCommands.ts

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*---------------------------------------------------------
2+
* Copyright (C) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------*/
4+
import * as vscode from "vscode";
5+
import { LanguageClient, RequestType } from "vscode-languageclient";
6+
import { IFeature } from "../feature";
7+
import { Logger } from "../logging";
8+
9+
interface ICommand {
10+
name: string;
11+
moduleName: string;
12+
defaultParameterSet: string;
13+
parameterSets: object;
14+
parameters: object;
15+
}
16+
17+
/**
18+
* RequestType sent over to PSES.
19+
* Expects: ICommand to be returned
20+
*/
21+
export const GetCommandRequestType = new RequestType<string, ICommand[], void, void>("powerShell/getCommand");
22+
23+
/**
24+
* A PowerShell Command listing feature. Implements a treeview control.
25+
*/
26+
export class GetCommandsFeature implements IFeature {
27+
private command: vscode.Disposable;
28+
private languageClient: LanguageClient;
29+
private commandsExplorerProvider: CommandsExplorerProvider;
30+
31+
constructor(private log: Logger) {
32+
this.command = vscode.commands.registerCommand("PowerShell.RefreshCommandsExplorer",
33+
() => this.CommandExplorerRefresh());
34+
this.commandsExplorerProvider = new CommandsExplorerProvider();
35+
vscode.window.registerTreeDataProvider("PowerShellCommands", this.commandsExplorerProvider);
36+
vscode.commands.registerCommand("PowerShell.InsertCommand", (item) => this.InsertCommand(item));
37+
}
38+
39+
public dispose() {
40+
this.command.dispose();
41+
}
42+
43+
public setLanguageClient(languageclient: LanguageClient) {
44+
this.languageClient = languageclient;
45+
vscode.commands.executeCommand("PowerShell.RefreshCommandsExplorer");
46+
}
47+
48+
private CommandExplorerRefresh() {
49+
if (this.languageClient === undefined) {
50+
this.log.writeAndShowError(`<${GetCommandsFeature.name}>: ` +
51+
"Unable to instantiate; language client undefined.");
52+
return;
53+
}
54+
this.languageClient.sendRequest(GetCommandRequestType, "").then((result) => {
55+
this.commandsExplorerProvider.powerShellCommands = result.map(toCommand);
56+
this.commandsExplorerProvider.refresh();
57+
});
58+
}
59+
60+
private InsertCommand(item) {
61+
const editor = vscode.window.activeTextEditor;
62+
const sls = editor.selection.start;
63+
const sle = editor.selection.end;
64+
const range = new vscode.Range(sls.line, sls.character, sle.line, sle.character);
65+
editor.edit((editBuilder) => {
66+
editBuilder.replace(range, item.Name);
67+
});
68+
}
69+
}
70+
71+
class CommandsExplorerProvider implements vscode.TreeDataProvider<Command> {
72+
public readonly onDidChangeTreeData: vscode.Event<Command | undefined>;
73+
public powerShellCommands: Command[];
74+
private didChangeTreeData: vscode.EventEmitter<Command | undefined> = new vscode.EventEmitter<Command>();
75+
76+
constructor() {
77+
this.onDidChangeTreeData = this.didChangeTreeData.event;
78+
}
79+
80+
public refresh(): void {
81+
this.didChangeTreeData.fire();
82+
}
83+
84+
public getTreeItem(element: Command): vscode.TreeItem {
85+
return element;
86+
}
87+
88+
public getChildren(element?: Command): Thenable<Command[]> {
89+
return Promise.resolve(this.powerShellCommands || []);
90+
}
91+
}
92+
93+
function toCommand(command: ICommand): Command {
94+
return new Command(
95+
command.name,
96+
command.moduleName,
97+
command.defaultParameterSet,
98+
command.parameterSets,
99+
command.parameters,
100+
);
101+
}
102+
103+
class Command extends vscode.TreeItem {
104+
constructor(
105+
public readonly Name: string,
106+
public readonly ModuleName: string,
107+
public readonly defaultParameterSet: string,
108+
public readonly ParameterSets: object,
109+
public readonly Parameters: object,
110+
public readonly collapsibleState = vscode.TreeItemCollapsibleState.None,
111+
) {
112+
super(Name, collapsibleState);
113+
}
114+
115+
public getTreeItem(): vscode.TreeItem {
116+
return {
117+
label: this.label,
118+
collapsibleState: this.collapsibleState,
119+
};
120+
}
121+
122+
public async getChildren(element?): Promise<Command[]> {
123+
return [];
124+
// Returning an empty array because we need to return something.
125+
}
126+
127+
}

src/features/ShowHelp.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,25 @@ export class ShowHelpFeature implements IFeature {
1616
private languageClient: LanguageClient;
1717

1818
constructor(private log: Logger) {
19-
this.command = vscode.commands.registerCommand("PowerShell.ShowHelp", () => {
19+
this.command = vscode.commands.registerCommand("PowerShell.ShowHelp", (item?) => {
2020
if (this.languageClient === undefined) {
2121
this.log.writeAndShowError(`<${ShowHelpFeature.name}>: ` +
2222
"Unable to instantiate; language client undefined.");
2323
return;
2424
}
25+
if (item === undefined) {
2526

26-
const editor = vscode.window.activeTextEditor;
27-
const selection = editor.selection;
28-
const doc = editor.document;
29-
const cwr = doc.getWordRangeAtPosition(selection.active);
30-
const text = doc.getText(cwr);
27+
const editor = vscode.window.activeTextEditor;
3128

32-
this.languageClient.sendRequest(ShowHelpRequestType, text);
29+
const selection = editor.selection;
30+
const doc = editor.document;
31+
const cwr = doc.getWordRangeAtPosition(selection.active);
32+
const text = doc.getText(cwr);
33+
34+
this.languageClient.sendRequest(ShowHelpRequestType, text);
35+
} else {
36+
this.languageClient.sendRequest(ShowHelpRequestType, item.Name);
37+
}
3338
});
3439

3540
this.deprecatedCommand = vscode.commands.registerCommand("PowerShell.OnlineHelp", () => {

src/main.ts

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ExtensionCommandsFeature } from "./features/ExtensionCommands";
2121
import { FindModuleFeature } from "./features/FindModule";
2222
import { FoldingFeature } from "./features/Folding";
2323
import { GenerateBugReportFeature } from "./features/GenerateBugReport";
24+
import { GetCommandsFeature } from "./features/GetCommands";
2425
import { HelpCompletionFeature } from "./features/HelpCompletion";
2526
import { NewFileOrProjectFeature } from "./features/NewFileOrProject";
2627
import { OpenInISEFeature } from "./features/OpenInISE";
@@ -123,6 +124,7 @@ export function activate(context: vscode.ExtensionContext): void {
123124
new OpenInISEFeature(),
124125
new GenerateBugReportFeature(sessionManager),
125126
new ExpandAliasFeature(logger),
127+
new GetCommandsFeature(logger),
126128
new ShowHelpFeature(logger),
127129
new FindModuleFeature(),
128130
new PesterTestsFeature(sessionManager),

0 commit comments

Comments
 (0)