[vscode-spring-cli]: boot new command support
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import cp from 'child_process';
|
||||
import { CliNewProjectMetadata, CliProjectType } from "./types";
|
||||
import { BootNewProjectMetadata, ProjectType } from "./types";
|
||||
import vscode from "vscode";
|
||||
|
||||
const SPRING_CLI_TASK_TYPE = 'spring-cli';
|
||||
|
||||
export class Cli {
|
||||
|
||||
getProjectTypes() : CliProjectType[] {
|
||||
getProjectTypes() : ProjectType[] {
|
||||
return [
|
||||
{
|
||||
id: 'web',
|
||||
@@ -29,15 +31,61 @@ export class Cli {
|
||||
];
|
||||
}
|
||||
|
||||
createProject(metadata: CliNewProjectMetadata) {
|
||||
this.exec(metadata.targetFolder, `spring boot new ${metadata.name} ${metadata.catalogType}`)
|
||||
createBootProject(metadata: BootNewProjectMetadata): Promise<void> {
|
||||
const args = [
|
||||
"boot",
|
||||
"new",
|
||||
"--name",
|
||||
`"${metadata.name}"`,
|
||||
"--from",
|
||||
`"${metadata.catalogType}"`
|
||||
];
|
||||
if (metadata.groupId) {
|
||||
args.push("--group-id")
|
||||
args.push(`"${metadata.groupId}"`);
|
||||
}
|
||||
if (metadata.artifactId) {
|
||||
args.push("--artifact-id")
|
||||
args.push(`"${metadata.artifactId}"`);
|
||||
}
|
||||
if (metadata.rootPackage) {
|
||||
args.push("--package-name");
|
||||
args.push(`"${metadata.rootPackage}"`);
|
||||
}
|
||||
return this.exec('Create Spring Boot project', `'${metadata.catalogType}'`, metadata.targetFolder, args);
|
||||
}
|
||||
|
||||
private exec(cwd: string, cmd: string) {
|
||||
cp.execSync(cmd, {
|
||||
cwd
|
||||
private async exec(title: string, message: string, cwd: string, args: string[]): Promise<void> {
|
||||
|
||||
return vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Window,
|
||||
cancellable: true,
|
||||
title
|
||||
}, (progress, cancellation) => {
|
||||
|
||||
progress.report({message});
|
||||
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
const process = new vscode.ProcessExecution('spring', args, { cwd });
|
||||
const task = new vscode.Task({ type: SPRING_CLI_TASK_TYPE}, vscode.workspace.getWorkspaceFolder(vscode.Uri.file(cwd)), `${title}: ${message}`, SPRING_CLI_TASK_TYPE, process);
|
||||
const taskExecution = await vscode.tasks.executeTask(task);
|
||||
if (cancellation.isCancellationRequested) {
|
||||
reject();
|
||||
}
|
||||
const cancelListener = cancellation.onCancellationRequested(() => {
|
||||
cancelListener.dispose();
|
||||
reject();
|
||||
})
|
||||
const listener = vscode.tasks.onDidEndTaskProcess(e => {
|
||||
if (e.execution === taskExecution) {
|
||||
listener.dispose();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface CliProjectType {
|
||||
export interface ProjectType {
|
||||
id: string;
|
||||
description?: string;
|
||||
url?: string;
|
||||
@@ -6,8 +6,10 @@ export interface CliProjectType {
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
export interface CliNewProjectMetadata {
|
||||
export interface BootNewProjectMetadata {
|
||||
name?: string;
|
||||
groupId?: string;
|
||||
artifactId?: string;
|
||||
catalogType?: string;
|
||||
rootPackage?: string;
|
||||
targetFolder?: string;
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
"use strict";
|
||||
import * as vscode from "vscode";
|
||||
import { Cli } from "./cli/core";
|
||||
import { handleCommand } from "./boot-project/project-new";
|
||||
import { handleNew } from "./boot-project/boot-project";
|
||||
|
||||
export const CLI = new Cli();
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||
vscode.commands.registerCommand('vscode-spring-cli.new-project', () => {
|
||||
handleCommand({});
|
||||
handleNew({});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OpenDialogOptions, Uri, window, workspace } from "vscode";
|
||||
import { InputBox, OpenDialogOptions, Uri, window, workspace } from "vscode";
|
||||
|
||||
export async function openDialogForFolder(customOptions: OpenDialogOptions): Promise<Uri> {
|
||||
const options: OpenDialogOptions = {
|
||||
@@ -15,3 +15,30 @@ export async function openDialogForFolder(customOptions: OpenDialogOptions): Pro
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
export function enterText(opts: {
|
||||
title: string,
|
||||
prompt: string,
|
||||
validate?: (v: string) => string | undefined,
|
||||
defaultValue?: string,
|
||||
placeholder?: string
|
||||
}): Promise<string> {
|
||||
return new Promise<string>((resolve) => {
|
||||
const inputBox: InputBox = window.createInputBox();
|
||||
inputBox.title = opts.title;
|
||||
inputBox.placeholder = opts.placeholder;
|
||||
inputBox.prompt = opts.prompt;
|
||||
inputBox.value = opts.defaultValue;
|
||||
inputBox.ignoreFocusOut = true;
|
||||
inputBox.onDidChangeValue(() => {
|
||||
inputBox.validationMessage = opts.validate ? opts.validate(inputBox.value) : undefined;
|
||||
});
|
||||
inputBox.onDidAccept(() => {
|
||||
if (!inputBox.validationMessage) {
|
||||
inputBox.hide();
|
||||
}
|
||||
});
|
||||
inputBox.onDidHide(() => resolve(inputBox.value));
|
||||
inputBox.show();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user