mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 21:32:05 +00:00
Implement VSCode tasks for bun (#5529)
* Fix VSCode extension configuration documentation * Fix config descriptions * Fix typo * Implement bun.lockb highlighter * Update style * Improve styling * Revert bunlock change * Implement bun tasks * Revert change * Package json codelens * Fixes * Refactor
This commit is contained in:
@@ -7,6 +7,10 @@
|
||||
"mime": "^3.0.0",
|
||||
"mime-db": "^1.52.0"
|
||||
},
|
||||
"scripts": {
|
||||
"run": "hello.js",
|
||||
"start": "bun hello.js"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"mime"
|
||||
],
|
||||
|
||||
@@ -54,13 +54,7 @@
|
||||
"../bun-inspector-protocol"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onLanguage:javascript",
|
||||
"onLanguage:javascriptreact",
|
||||
"onLanguage:typescript",
|
||||
"onLanguage:typescriptreact",
|
||||
"workspaceContains:**/.lockb",
|
||||
"onDebugResolve:bun",
|
||||
"onDebugDynamicConfigurations:bun"
|
||||
"onStartupFinished"
|
||||
],
|
||||
"browser": "dist/web-extension.js",
|
||||
"bugs": {
|
||||
@@ -294,6 +288,20 @@
|
||||
],
|
||||
"priority": "default"
|
||||
}
|
||||
],
|
||||
"taskDefinitions": [
|
||||
{
|
||||
"type": "bun",
|
||||
"required": [
|
||||
"script"
|
||||
],
|
||||
"properties": {
|
||||
"script": {
|
||||
"type": "string",
|
||||
"description": "The script to execute"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ buildSync({
|
||||
external: ["vscode"],
|
||||
platform: "node",
|
||||
format: "cjs",
|
||||
|
||||
// The following settings are required to allow for extension debugging
|
||||
minify: false,
|
||||
sourcemap: true,
|
||||
});
|
||||
|
||||
rmSync("extension", { recursive: true, force: true });
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import * as vscode from "vscode";
|
||||
import activateLockfile from "./features/lockfile";
|
||||
import activateDebug from "./features/debug";
|
||||
import { registerTaskProvider } from "./features/tasks/tasks";
|
||||
import { registerDebugger } from "./features/debug";
|
||||
import { registerPackageJsonProviders } from "./features/tasks/package.json";
|
||||
import { registerBunlockEditor } from "./features/lockfile";
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
activateLockfile(context);
|
||||
activateDebug(context);
|
||||
registerBunlockEditor(context);
|
||||
registerDebugger(context);
|
||||
registerTaskProvider(context);
|
||||
registerPackageJsonProviders(context);
|
||||
}
|
||||
|
||||
export function deactivate() {}
|
||||
|
||||
@@ -4,43 +4,44 @@ import { DebugAdapter, UnixSignal } from "../../../bun-debug-adapter-protocol";
|
||||
import { DebugSession } from "@vscode/debugadapter";
|
||||
import { tmpdir } from "node:os";
|
||||
|
||||
const debugConfiguration: vscode.DebugConfiguration = {
|
||||
export const DEBUG_CONFIGURATION: vscode.DebugConfiguration = {
|
||||
type: "bun",
|
||||
internalConsoleOptions: "neverOpen",
|
||||
request: "launch",
|
||||
name: "Debug File",
|
||||
program: "${file}",
|
||||
cwd: "${workspaceFolder}",
|
||||
stopOnEntry: false,
|
||||
watchMode: false,
|
||||
internalConsoleOptions: "neverOpen",
|
||||
|
||||
};
|
||||
|
||||
const runConfiguration: vscode.DebugConfiguration = {
|
||||
export const RUN_CONFIGURATION: vscode.DebugConfiguration = {
|
||||
type: "bun",
|
||||
internalConsoleOptions: "neverOpen",
|
||||
request: "launch",
|
||||
name: "Run File",
|
||||
program: "${file}",
|
||||
cwd: "${workspaceFolder}",
|
||||
noDebug: true,
|
||||
watchMode: false,
|
||||
internalConsoleOptions: "neverOpen",
|
||||
};
|
||||
|
||||
const attachConfiguration: vscode.DebugConfiguration = {
|
||||
const ATTACH_CONFIGURATION: vscode.DebugConfiguration = {
|
||||
type: "bun",
|
||||
internalConsoleOptions: "neverOpen",
|
||||
request: "attach",
|
||||
name: "Attach Bun",
|
||||
url: "ws://localhost:6499/",
|
||||
stopOnEntry: false,
|
||||
internalConsoleOptions: "neverOpen",
|
||||
};
|
||||
|
||||
const adapters = new Map<string, FileDebugSession>();
|
||||
|
||||
export default function (context: vscode.ExtensionContext, factory?: vscode.DebugAdapterDescriptorFactory) {
|
||||
export function registerDebugger(context: vscode.ExtensionContext, factory?: vscode.DebugAdapterDescriptorFactory) {
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand("extension.bun.runFile", RunFileCommand),
|
||||
vscode.commands.registerCommand("extension.bun.debugFile", DebugFileCommand),
|
||||
vscode.commands.registerCommand("extension.bun.runFile", runFileCommand),
|
||||
vscode.commands.registerCommand("extension.bun.debugFile", debugFileCommand),
|
||||
vscode.debug.registerDebugConfigurationProvider(
|
||||
"bun",
|
||||
new DebugConfigurationProvider(),
|
||||
@@ -52,15 +53,15 @@ export default function (context: vscode.ExtensionContext, factory?: vscode.Debu
|
||||
vscode.DebugConfigurationProviderTriggerKind.Dynamic,
|
||||
),
|
||||
vscode.debug.registerDebugAdapterDescriptorFactory("bun", factory ?? new InlineDebugAdapterFactory()),
|
||||
vscode.window.onDidOpenTerminal(InjectDebugTerminal),
|
||||
vscode.window.onDidOpenTerminal(injectDebugTerminal),
|
||||
);
|
||||
}
|
||||
|
||||
function RunFileCommand(resource?: vscode.Uri): void {
|
||||
function runFileCommand(resource?: vscode.Uri): void {
|
||||
const path = getActivePath(resource);
|
||||
if (path) {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
...runConfiguration,
|
||||
...RUN_CONFIGURATION,
|
||||
noDebug: true,
|
||||
program: path,
|
||||
runtime: getRuntime(resource),
|
||||
@@ -68,22 +69,21 @@ function RunFileCommand(resource?: vscode.Uri): void {
|
||||
}
|
||||
}
|
||||
|
||||
function DebugFileCommand(resource?: vscode.Uri): void {
|
||||
const path = getActivePath(resource);
|
||||
if (path) {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
...debugConfiguration,
|
||||
program: path,
|
||||
runtime: getRuntime(resource),
|
||||
});
|
||||
}
|
||||
export function debugCommand(command: string) {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
...DEBUG_CONFIGURATION,
|
||||
program: command,
|
||||
runtime: getRuntime(),
|
||||
});
|
||||
}
|
||||
|
||||
function InjectDebugTerminal(terminal: vscode.Terminal): void {
|
||||
const enabled = getConfig("debugTerminal.enabled");
|
||||
if (enabled === false) {
|
||||
return;
|
||||
}
|
||||
function debugFileCommand(resource?: vscode.Uri) {
|
||||
const path = getActivePath(resource);
|
||||
if (path) debugCommand(path);
|
||||
}
|
||||
|
||||
function injectDebugTerminal(terminal: vscode.Terminal): void {
|
||||
if (!getConfig("debugTerminal.enabled")) return
|
||||
|
||||
const { name, creationOptions } = terminal;
|
||||
if (name !== "JavaScript Debug Terminal") {
|
||||
@@ -118,16 +118,9 @@ function InjectDebugTerminal(terminal: vscode.Terminal): void {
|
||||
setTimeout(() => terminal.dispose(), 100);
|
||||
}
|
||||
|
||||
class TerminalProfileProvider implements vscode.TerminalProfileProvider {
|
||||
provideTerminalProfile(token: vscode.CancellationToken): vscode.ProviderResult<vscode.TerminalProfile> {
|
||||
const { terminalProfile } = new TerminalDebugSession();
|
||||
return terminalProfile;
|
||||
}
|
||||
}
|
||||
|
||||
class DebugConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
provideDebugConfigurations(folder?: vscode.WorkspaceFolder): vscode.ProviderResult<vscode.DebugConfiguration[]> {
|
||||
return [debugConfiguration, runConfiguration, attachConfiguration];
|
||||
return [DEBUG_CONFIGURATION, RUN_CONFIGURATION, ATTACH_CONFIGURATION];
|
||||
}
|
||||
|
||||
resolveDebugConfiguration(
|
||||
@@ -139,9 +132,9 @@ class DebugConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
|
||||
const { request } = config;
|
||||
if (request === "attach") {
|
||||
target = attachConfiguration;
|
||||
target = ATTACH_CONFIGURATION;
|
||||
} else {
|
||||
target = debugConfiguration;
|
||||
target = DEBUG_CONFIGURATION;
|
||||
}
|
||||
|
||||
// If the configuration is missing a default property, copy it from the template.
|
||||
@@ -219,7 +212,7 @@ class TerminalDebugSession extends FileDebugSession {
|
||||
this.signal = new UnixSignal();
|
||||
this.signal.on("Signal.received", () => {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
...attachConfiguration,
|
||||
...ATTACH_CONFIGURATION,
|
||||
url: this.adapter.url,
|
||||
});
|
||||
});
|
||||
@@ -238,34 +231,19 @@ class TerminalDebugSession extends FileDebugSession {
|
||||
}
|
||||
}
|
||||
|
||||
function getActiveDocument(): vscode.TextDocument | undefined {
|
||||
return vscode.window.activeTextEditor?.document;
|
||||
}
|
||||
|
||||
function getActivePath(target?: vscode.Uri): string | undefined {
|
||||
if (!target) {
|
||||
target = getActiveDocument()?.uri;
|
||||
}
|
||||
return target?.fsPath;
|
||||
}
|
||||
|
||||
function isJavaScript(languageId?: string): boolean {
|
||||
return (
|
||||
languageId === "javascript" ||
|
||||
languageId === "javascriptreact" ||
|
||||
languageId === "typescript" ||
|
||||
languageId === "typescriptreact"
|
||||
);
|
||||
return target?.fsPath ?? vscode.window.activeTextEditor?.document?.uri.fsPath;
|
||||
}
|
||||
|
||||
function getRuntime(scope?: vscode.ConfigurationScope): string {
|
||||
const value = getConfig("runtime", scope);
|
||||
const value = getConfig<string>("runtime", scope);
|
||||
if (typeof value === "string" && value.trim().length > 0) {
|
||||
return value;
|
||||
}
|
||||
return "bun";
|
||||
}
|
||||
|
||||
function getConfig<T>(path: string, scope?: vscode.ConfigurationScope): unknown {
|
||||
return vscode.workspace.getConfiguration("bun", scope).get(path);
|
||||
function getConfig<T>(path: string, scope?: vscode.ConfigurationScope) {
|
||||
return vscode.workspace.getConfiguration("bun", scope).get<T>(path);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ export class BunLockfileEditorProvider implements vscode.CustomReadonlyEditorPro
|
||||
function renderLockfile({ webview }: vscode.WebviewPanel, preview: string, extensionUri: vscode.Uri): void {
|
||||
const styleVSCodeUri = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, "media", "vscode.css"));
|
||||
const lockfileContent = styleLockfile(preview);
|
||||
|
||||
const lineNumbers: string[] = []
|
||||
for(let i = 0; i < lockfileContent.split('\n').length; i++){
|
||||
lineNumbers.push(`<span class="line-number">${i + 1}</span>`)
|
||||
|
||||
const lineNumbers: string[] = [];
|
||||
for (let i = 0; i < lockfileContent.split("\n").length; i++) {
|
||||
lineNumbers.push(`<span class="line-number">${i + 1}</span>`);
|
||||
}
|
||||
|
||||
webview.html = `
|
||||
@@ -50,7 +50,7 @@ function renderLockfile({ webview }: vscode.WebviewPanel, preview: string, exten
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource};">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource};">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
@@ -59,7 +59,7 @@ function renderLockfile({ webview }: vscode.WebviewPanel, preview: string, exten
|
||||
<body>
|
||||
<div class="bunlock">
|
||||
<div class="lines">
|
||||
${lineNumbers.join('\n')}
|
||||
${lineNumbers.join("\n")}
|
||||
</div>
|
||||
<code>${lockfileContent}</code>
|
||||
</div>
|
||||
@@ -96,15 +96,17 @@ function previewLockfile(uri: vscode.Uri, token?: vscode.CancellationToken): Pro
|
||||
});
|
||||
}
|
||||
|
||||
export default function (context: vscode.ExtensionContext): void {
|
||||
export function registerBunlockEditor(context: vscode.ExtensionContext): void {
|
||||
const viewType = "bun.lockb";
|
||||
const provider = new BunLockfileEditorProvider(context);
|
||||
|
||||
vscode.window.registerCustomEditorProvider(viewType, provider, {
|
||||
supportsMultipleEditorsPerDocument: true,
|
||||
webviewOptions: {
|
||||
enableFindWidget: true,
|
||||
retainContextWhenHidden: true,
|
||||
},
|
||||
});
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerCustomEditorProvider(viewType, provider, {
|
||||
supportsMultipleEditorsPerDocument: true,
|
||||
webviewOptions: {
|
||||
enableFindWidget: true,
|
||||
retainContextWhenHidden: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
35
packages/bun-vscode/src/features/lockfile/lockfile.style.ts
Normal file
35
packages/bun-vscode/src/features/lockfile/lockfile.style.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export function styleLockfile(preview: string) {
|
||||
// Match all lines that don't start with a whitespace character
|
||||
const lines = preview.split(/\n(?!\s)/);
|
||||
|
||||
return lines.map(styleSection).join("\n");
|
||||
}
|
||||
|
||||
function styleSection(section: string) {
|
||||
const lines = section.split(/\n/);
|
||||
|
||||
return lines.map(styleLine).join("\n");
|
||||
}
|
||||
|
||||
function styleLine(line: string) {
|
||||
if (line.startsWith("#")) {
|
||||
return `<span class="mtk5">${line}</span>`;
|
||||
}
|
||||
|
||||
const parts = line.trim().split(" ");
|
||||
if (line.startsWith(" ")) {
|
||||
return `<span><span class="mtk1"> ${parts[0]} </span><span class="mtk16">${parts[1]}</span></span>`;
|
||||
}
|
||||
if (line.startsWith(" ")) {
|
||||
const leftPart = `<span class="mtk6"> ${parts[0]} </span>`;
|
||||
|
||||
if (parts.length === 1) return `<span>${leftPart}</span>`;
|
||||
|
||||
if (parts[1].startsWith('"http://') || parts[1].startsWith('"https://'))
|
||||
return `<span>${leftPart}<span class="mtk12 detected-link">${parts[1]}</span></span>`;
|
||||
if (parts[1].startsWith('"')) return `<span>${leftPart}<span class="mtk16">${parts[1]}</span></span>`;
|
||||
|
||||
return `<span>${leftPart}<span class="mtk6">${parts[1]}</span></span>`;
|
||||
}
|
||||
return `<span class="mtk1">${line} </span>`;
|
||||
}
|
||||
197
packages/bun-vscode/src/features/tasks/package.json.ts
Normal file
197
packages/bun-vscode/src/features/tasks/package.json.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* Automatically generates tasks from package.json scripts.
|
||||
*/
|
||||
import * as vscode from "vscode";
|
||||
import { BunTask } from "./tasks";
|
||||
import { debugCommand } from "../debug";
|
||||
|
||||
/**
|
||||
* Parses tasks defined in the package.json.
|
||||
*/
|
||||
export async function providePackageJsonTasks(): Promise<BunTask[]> {
|
||||
//
|
||||
const scripts: Record<string, string> = await (async () => {
|
||||
try {
|
||||
const file = vscode.Uri.file(vscode.workspace.workspaceFolders[0]?.uri.fsPath + "/package.json");
|
||||
|
||||
// Load contents of package.json, no need to check if file exists, we return null if it doesn't
|
||||
const contents = await vscode.workspace.fs.readFile(file);
|
||||
return JSON.parse(contents.toString()).scripts;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
if (!scripts) return [];
|
||||
|
||||
return Object.entries(scripts).map(([name, script]) => {
|
||||
// Prefix script with bun if it doesn't already start with bun
|
||||
const shellCommand = script.startsWith("bun") ? script : `bun ${script}`;
|
||||
|
||||
const task = new BunTask({
|
||||
script,
|
||||
name,
|
||||
detail: `${shellCommand} - package.json`,
|
||||
execution: new vscode.ShellExecution(shellCommand),
|
||||
});
|
||||
return task;
|
||||
});
|
||||
}
|
||||
|
||||
export function registerPackageJsonProviders(context: vscode.ExtensionContext) {
|
||||
registerCodeLensProvider(context);
|
||||
registerHoverProvider(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to extract the scripts from a package.json file, including their name and position in the document.
|
||||
*/
|
||||
function extractScriptsFromPackageJson(document: vscode.TextDocument) {
|
||||
const content = document.getText();
|
||||
const matches = content.match(/"scripts"\s*:\s*{([\s\S]*?)}/);
|
||||
if (!matches || matches.length < 2) return null;
|
||||
|
||||
const startIndex = content.indexOf(matches[0]);
|
||||
const endIndex = startIndex + matches[0].length;
|
||||
const range = new vscode.Range(document.positionAt(startIndex), document.positionAt(endIndex));
|
||||
|
||||
const scripts = matches[1].split(/,\s*/).map(script => {
|
||||
const [name, command] = script.split(/s*:\s*/);
|
||||
return {
|
||||
name: name.replace(/"/g, "").trim(),
|
||||
command: command.replace(/"/g, "").trim(),
|
||||
range: new vscode.Range(
|
||||
document.positionAt(startIndex + matches[0].indexOf(name)),
|
||||
document.positionAt(startIndex + matches[0].indexOf(name) + name.length + command.length),
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
range,
|
||||
scripts,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This function registers a CodeLens provider for package.json files. It is used to display the "Run" and "Debug" buttons
|
||||
* above the scripts properties in package.json (inline).
|
||||
*/
|
||||
function registerCodeLensProvider(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(
|
||||
// Register CodeLens provider for package.json files
|
||||
vscode.languages.registerCodeLensProvider(
|
||||
{
|
||||
language: "json",
|
||||
scheme: "file",
|
||||
pattern: "**/package.json",
|
||||
},
|
||||
{
|
||||
provideCodeLenses(document: vscode.TextDocument) {
|
||||
const { range } = extractScriptsFromPackageJson(document);
|
||||
|
||||
const codeLenses: vscode.CodeLens[] = [];
|
||||
codeLenses.push(
|
||||
new vscode.CodeLens(range, {
|
||||
title: "$(breakpoints-view-icon) Bun: Debug",
|
||||
tooltip: "Debug a script using bun",
|
||||
command: "extension.bun.codelens.run",
|
||||
arguments: [{ type: "debug" }],
|
||||
}),
|
||||
new vscode.CodeLens(range, {
|
||||
title: "$(debug-start) Bun: Run",
|
||||
tooltip: "Run a script using bun",
|
||||
command: "extension.bun.codelens.run",
|
||||
arguments: [{ type: "run" }],
|
||||
}),
|
||||
);
|
||||
return codeLenses;
|
||||
},
|
||||
resolveCodeLens(codeLens) {
|
||||
return codeLens;
|
||||
},
|
||||
},
|
||||
),
|
||||
// Register the commands that are executed when clicking the CodeLens buttons
|
||||
vscode.commands.registerCommand("extension.bun.codelens.run", async ({ type }: { type: "debug" | "run" }) => {
|
||||
const tasks = (await vscode.tasks.fetchTasks({ type: "bun" })) as BunTask[];
|
||||
if (tasks.length === 0) return;
|
||||
|
||||
const pick = await vscode.window.showQuickPick(
|
||||
tasks
|
||||
.filter(task => task.detail.endsWith("package.json"))
|
||||
.map(task => ({
|
||||
label: task.name,
|
||||
detail: task.detail,
|
||||
})),
|
||||
);
|
||||
if (!pick) return;
|
||||
|
||||
const task = tasks.find(task => task.name === pick.label);
|
||||
if (!task) return;
|
||||
|
||||
const command = type === "debug" ? "extension.bun.codelens.debug.task" : "extension.bun.codelens.run.task";
|
||||
|
||||
vscode.commands.executeCommand(command, {
|
||||
script: task.definition.script,
|
||||
name: task.name,
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function getActiveTerminal(name: string) {
|
||||
return vscode.window.terminals.filter(terminal => terminal.name === name);
|
||||
}
|
||||
|
||||
interface CommandArgs {
|
||||
script: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function registers a Hover language feature provider for package.json files. It is used to display the
|
||||
* "Run" and "Debug" buttons when hovering over a script property in package.json.
|
||||
*/
|
||||
function registerHoverProvider(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(
|
||||
vscode.languages.registerHoverProvider("json", {
|
||||
provideHover(document, position) {
|
||||
const { scripts } = extractScriptsFromPackageJson(document);
|
||||
|
||||
return {
|
||||
contents: scripts.map(script => {
|
||||
if (!script.range.contains(position)) return null;
|
||||
|
||||
const command = encodeURI(JSON.stringify({ script: script.command, name: script.name }));
|
||||
|
||||
const markdownString = new vscode.MarkdownString(
|
||||
`[Debug](command:extension.bun.codelens.debug.task?${command}) | [Run](command:extension.bun.codelens.run.task?${command})`,
|
||||
);
|
||||
markdownString.isTrusted = true;
|
||||
|
||||
return markdownString;
|
||||
}),
|
||||
};
|
||||
},
|
||||
}),
|
||||
vscode.commands.registerCommand("extension.bun.codelens.debug.task", async ({ script, name }: CommandArgs) => {
|
||||
if (script.startsWith("bun ")) script = script.slice(4);
|
||||
debugCommand(script);
|
||||
}),
|
||||
vscode.commands.registerCommand("extension.bun.codelens.run.task", async ({ script, name }: CommandArgs) => {
|
||||
if (script.startsWith("bun ")) script = script.slice(4);
|
||||
|
||||
name = `Bun Task: ${name}`;
|
||||
const terminals = getActiveTerminal(name);
|
||||
if (terminals.length > 0) {
|
||||
terminals[0].show();
|
||||
terminals[0].sendText(`bun ${script}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const terminal = vscode.window.createTerminal({name});
|
||||
terminal.show();
|
||||
terminal.sendText(`bun ${script}`);
|
||||
}),
|
||||
);
|
||||
}
|
||||
59
packages/bun-vscode/src/features/tasks/tasks.ts
Normal file
59
packages/bun-vscode/src/features/tasks/tasks.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import * as vscode from "vscode";
|
||||
import { providePackageJsonTasks } from "./package.json";
|
||||
|
||||
interface BunTaskDefinition extends vscode.TaskDefinition {
|
||||
script: string;
|
||||
}
|
||||
|
||||
export class BunTask extends vscode.Task {
|
||||
declare definition: BunTaskDefinition;
|
||||
|
||||
constructor({
|
||||
script,
|
||||
name,
|
||||
detail,
|
||||
execution,
|
||||
scope = vscode.TaskScope.Workspace,
|
||||
}: {
|
||||
script: string;
|
||||
name: string;
|
||||
detail?: string;
|
||||
scope?: vscode.WorkspaceFolder | vscode.TaskScope.Global | vscode.TaskScope.Workspace;
|
||||
execution?: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution;
|
||||
}) {
|
||||
super({ type: "bun", script }, scope, name, "bun", execution);
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the task provider for the bun extension.
|
||||
*/
|
||||
export function registerTaskProvider(context: vscode.ExtensionContext) {
|
||||
const taskProvider: vscode.TaskProvider<BunTask> = {
|
||||
provideTasks: async () => await providePackageJsonTasks(),
|
||||
resolveTask: task => resolveTask(task),
|
||||
};
|
||||
context.subscriptions.push(vscode.tasks.registerTaskProvider("bun", taskProvider));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses tasks defined in the vscode tasks.json file.
|
||||
* For more information, see https://code.visualstudio.com/api/extension-guides/task-provider
|
||||
*/
|
||||
export function resolveTask(task: BunTask): BunTask | undefined {
|
||||
// Make sure the task has a script defined
|
||||
const definition: BunTask["definition"] = task.definition;
|
||||
if (!definition.script) return task;
|
||||
const shellCommand = definition.script.startsWith("bun ") ? definition.script : `bun ${definition.script}`;
|
||||
|
||||
const newTask = new vscode.Task(
|
||||
definition,
|
||||
task.scope ?? vscode.TaskScope.Workspace,
|
||||
task.name,
|
||||
"bun",
|
||||
new vscode.ShellExecution(shellCommand),
|
||||
) as BunTask;
|
||||
newTask.detail = `${shellCommand} - tasks.json`;
|
||||
return newTask;
|
||||
}
|
||||
Reference in New Issue
Block a user