Ground work for Spring-CLI extension
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import * as path from "path";
|
||||
import { CliNewProjectMetadata, CliProjectType } from "../cli/types";
|
||||
import { CLI } from "../extension";
|
||||
import { openDialogForFolder } from "../utils";
|
||||
import vscode, { InputBox, QuickPickItem, QuickPickItemKind } from 'vscode';
|
||||
|
||||
const OPEN_IN_NEW_WORKSPACE = "Open";
|
||||
const OPEN_IN_CURRENT_WORKSPACE = "Add to Workspace";
|
||||
|
||||
export async function handleCommand(metadata: CliNewProjectMetadata) {
|
||||
if (!metadata.catalogType) {
|
||||
const item = await vscode.window.showQuickPick(CLI.getProjectTypes().map(mapProjectTypetoQuickPick), { canPickMany: false });
|
||||
if (item) {
|
||||
metadata.catalogType = item.label;
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const inputBox: InputBox = vscode.window.createInputBox();
|
||||
inputBox.title = 'Project Name';
|
||||
inputBox.placeholder = metadata.name || metadata.catalogType;
|
||||
inputBox.prompt = 'Enter project name';
|
||||
inputBox.value = metadata.name;
|
||||
inputBox.ignoreFocusOut = true;
|
||||
inputBox.onDidAccept(() => {
|
||||
metadata.name = inputBox.value;
|
||||
inputBox.hide();
|
||||
});
|
||||
inputBox.onDidHide(() => resolve());
|
||||
inputBox.show();
|
||||
});
|
||||
|
||||
metadata.rootPackage = 'com.example.demo';
|
||||
|
||||
metadata.targetFolder = (await openDialogForFolder({})).fsPath;
|
||||
|
||||
if (metadata.name && metadata.catalogType && metadata.targetFolder) {
|
||||
vscode.window.showInformationMessage(`Folder="${metadata.targetFolder}" Command="spring boot new ${metadata.name} ${metadata.catalogType}"`)
|
||||
CLI.createProject(metadata);
|
||||
|
||||
// Open project either is the same workspace or new workspace
|
||||
const hasOpenFolder = vscode.workspace.workspaceFolders !== undefined || vscode.workspace.rootPath !== undefined;
|
||||
|
||||
const pathToOpen = path.resolve(metadata.targetFolder, metadata.name);
|
||||
|
||||
// Don't prompt to open projectLocation if it's already a currently opened folder
|
||||
if (hasOpenFolder && (vscode.workspace.workspaceFolders.some(folder => folder.uri.fsPath === pathToOpen) || vscode.workspace.rootPath === pathToOpen)) {
|
||||
return;
|
||||
}
|
||||
const choice = await specifyOpenMethod(hasOpenFolder, vscode.Uri.file(pathToOpen))
|
||||
|
||||
if (choice === OPEN_IN_NEW_WORKSPACE) {
|
||||
vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(pathToOpen), hasOpenFolder);
|
||||
} else if (choice === OPEN_IN_CURRENT_WORKSPACE) {
|
||||
if (!vscode.workspace.workspaceFolders.find((workspaceFolder) => workspaceFolder.uri && pathToOpen.startsWith(workspaceFolder.uri.fsPath))) {
|
||||
vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders.length, null, { uri: vscode.Uri.file(pathToOpen) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function mapProjectTypetoQuickPick(metadata: CliProjectType): QuickPickItem {
|
||||
return {
|
||||
label: metadata.id,
|
||||
kind: QuickPickItemKind.Default,
|
||||
description: metadata.description,
|
||||
detail: metadata.tags.toString()
|
||||
};
|
||||
}
|
||||
|
||||
async function specifyOpenMethod(hasOpenFolder: boolean, projectLocation: vscode.Uri): Promise<string> {
|
||||
const candidates: string[] = [
|
||||
OPEN_IN_NEW_WORKSPACE,
|
||||
hasOpenFolder ? OPEN_IN_CURRENT_WORKSPACE : undefined,
|
||||
].filter(Boolean);
|
||||
return await vscode.window.showInformationMessage(`Successfully generated. Location: ${projectLocation.fsPath}`, ...candidates);
|
||||
}
|
||||
43
vscode-extensions/vscode-spring-cli/src/cli/core.ts
Normal file
43
vscode-extensions/vscode-spring-cli/src/cli/core.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import cp from 'child_process';
|
||||
import { CliNewProjectMetadata, CliProjectType } from "./types";
|
||||
|
||||
export class Cli {
|
||||
|
||||
getProjectTypes() : CliProjectType[] {
|
||||
return [
|
||||
{
|
||||
id: 'web',
|
||||
description: 'Hello, World RESTful web service.',
|
||||
url: 'https://github.com/rd-1-2022/rest-service',
|
||||
catalogId: 'gs',
|
||||
tags: ['java-17', 'boot-3.1.x', 'rest', 'web']
|
||||
},
|
||||
{
|
||||
id: 'jpa',
|
||||
description: 'Learn how to work with JPA data persistence using Spring Data JPA.',
|
||||
url: 'https://github.com/rd-1-2022/rpt-spring-data-jpa',
|
||||
catalogId: 'gs',
|
||||
tags: ['java-17', 'boot-3.1.x', 'jpa', 'h2']
|
||||
},
|
||||
{
|
||||
id: 'scheduling',
|
||||
description: 'How to schedule tasks',
|
||||
url: 'https://github.com/rd-1-2022/rpt-spring-scheduling-tasks',
|
||||
catalogId: 'gs',
|
||||
tags: ['scheduling']
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
createProject(metadata: CliNewProjectMetadata) {
|
||||
this.exec(metadata.targetFolder, `spring boot new ${metadata.name} ${metadata.catalogType}`)
|
||||
}
|
||||
|
||||
private exec(cwd: string, cmd: string) {
|
||||
cp.execSync(cmd, {
|
||||
cwd
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
14
vscode-extensions/vscode-spring-cli/src/cli/types.ts
Normal file
14
vscode-extensions/vscode-spring-cli/src/cli/types.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface CliProjectType {
|
||||
id: string;
|
||||
description?: string;
|
||||
url?: string;
|
||||
catalogId: string;
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
export interface CliNewProjectMetadata {
|
||||
name?: string;
|
||||
catalogType?: string;
|
||||
rootPackage?: string;
|
||||
targetFolder?: string;
|
||||
}
|
||||
18
vscode-extensions/vscode-spring-cli/src/extension.ts
Normal file
18
vscode-extensions/vscode-spring-cli/src/extension.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
"use strict";
|
||||
import * as vscode from "vscode";
|
||||
import { Cli } from "./cli/core";
|
||||
import { handleCommand } from "./boot-project/project-new";
|
||||
|
||||
export const CLI = new Cli();
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||
vscode.commands.registerCommand('vscode-spring-cli.new-project', () => {
|
||||
handleCommand({});
|
||||
});
|
||||
}
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
}
|
||||
17
vscode-extensions/vscode-spring-cli/src/utils.ts
Normal file
17
vscode-extensions/vscode-spring-cli/src/utils.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { OpenDialogOptions, Uri, window, workspace } from "vscode";
|
||||
|
||||
export async function openDialogForFolder(customOptions: OpenDialogOptions): Promise<Uri> {
|
||||
const options: OpenDialogOptions = {
|
||||
canSelectFiles: false,
|
||||
canSelectFolders: true,
|
||||
canSelectMany: false,
|
||||
// default to current workspace folder (pick 1st one in multi-root)
|
||||
defaultUri: workspace.workspaceFolders && workspace.workspaceFolders.length > 0 ? workspace.workspaceFolders[0].uri : undefined
|
||||
};
|
||||
const result: Uri[] = await window.showOpenDialog(Object.assign(options, customOptions));
|
||||
if (result && result.length) {
|
||||
return Promise.resolve(result[0]);
|
||||
} else {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user