mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-13 23:44:09 +01:00
Share exec/spawn code between shells
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import type { ICompletionResource } from '../types';
|
||||
import { exec, spawn, type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
import { type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
import { execHelper, spawnHelper } from './common';
|
||||
|
||||
export async function getBashGlobals(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<(string | ICompletionResource)[]> {
|
||||
return [
|
||||
@@ -15,15 +16,7 @@ export async function getBashGlobals(options: ExecOptionsWithStringEncoding, exi
|
||||
}
|
||||
|
||||
async function getBuiltins(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<string[]> {
|
||||
const compgenOutput = await new Promise<string>((resolve, reject) => {
|
||||
exec('compgen -b', options, (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
const compgenOutput = await execHelper('compgen -b', options);
|
||||
const filter = (cmd: string) => cmd && !existingCommands?.has(cmd);
|
||||
return compgenOutput.split('\n').filter(filter);
|
||||
}
|
||||
@@ -33,21 +26,7 @@ async function getAliases(options: ExecOptionsWithStringEncoding): Promise<IComp
|
||||
// be set up. Note that this could differ from the actual aliases as it's a new bash
|
||||
// session, for the same reason this would not include aliases that are created
|
||||
// by simply running `alias ...` in the terminal.
|
||||
const aliasOutput = await new Promise<string>((resolve, reject) => {
|
||||
const child = spawn('bash', ['-ic', 'alias'], options);
|
||||
let stdout = '';
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(`bash process exited with code ${code}`));
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const aliasOutput = await spawnHelper('bash', ['-ic', 'alias'], options);
|
||||
const result: ICompletionResource[] = [];
|
||||
for (const line of aliasOutput.split('\n')) {
|
||||
const match = line.match(/^alias (?<alias>[a-zA-Z0-9\.:-]+)='(?<resolved>.+)'$/);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { exec, spawn, type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
|
||||
export async function spawnHelper(command: string, args: string[], options: ExecOptionsWithStringEncoding): Promise<string> {
|
||||
// This must be run with interactive, otherwise there's a good chance aliases won't
|
||||
// be set up. Note that this could differ from the actual aliases as it's a new bash
|
||||
// session, for the same reason this would not include aliases that are created
|
||||
// by simply running `alias ...` in the terminal.
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const child = spawn(command, args, options);
|
||||
let stdout = '';
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(`bash process exited with code ${code}`));
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function execHelper(commandLine: string, options: ExecOptionsWithStringEncoding): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
exec(commandLine, options, (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import type { ICompletionResource } from '../types';
|
||||
import { exec, spawn, type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
import { execHelper, spawnHelper } from './common';
|
||||
import { type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
|
||||
export async function getFishGlobals(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<(string | ICompletionResource)[]> {
|
||||
return [
|
||||
@@ -15,15 +16,7 @@ export async function getFishGlobals(options: ExecOptionsWithStringEncoding, exi
|
||||
}
|
||||
|
||||
async function getBuiltins(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<string[]> {
|
||||
const compgenOutput = await new Promise<string>((resolve, reject) => {
|
||||
exec('functions -n', options, (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
const compgenOutput = await execHelper('functions -n', options);
|
||||
const filter = (cmd: string) => cmd && !existingCommands?.has(cmd);
|
||||
return compgenOutput.split(', ').filter(filter);
|
||||
}
|
||||
@@ -33,20 +26,7 @@ async function getAliases(options: ExecOptionsWithStringEncoding): Promise<IComp
|
||||
// be set up. Note that this could differ from the actual aliases as it's a new bash
|
||||
// session, for the same reason this would not include aliases that are created
|
||||
// by simply running `alias ...` in the terminal.
|
||||
const aliasOutput = await new Promise<string>((resolve, reject) => {
|
||||
const child = spawn('fish', ['-ic', 'alias'], options);
|
||||
let stdout = '';
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(`bash process exited with code ${code}`));
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
const aliasOutput = await spawnHelper('fish', ['-ic', 'alias'], options);
|
||||
|
||||
const result: ICompletionResource[] = [];
|
||||
for (const line of aliasOutput.split('\n')) {
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import type { ICompletionResource } from '../types';
|
||||
import { exec, type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
import { type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
import { execHelper } from './common';
|
||||
|
||||
export async function getPwshGlobals(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<(string | ICompletionResource)[]> {
|
||||
return [
|
||||
@@ -18,18 +19,9 @@ const enum PwshCommandType {
|
||||
}
|
||||
|
||||
async function getCommands(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<ICompletionResource[]> {
|
||||
|
||||
const output = await new Promise<string>((resolve, reject) => {
|
||||
exec('Get-Command -All | Select-Object Name, CommandType, DisplayName, Definition | ConvertTo-Json', {
|
||||
...options,
|
||||
maxBuffer: 1024 * 1024 * 100 // This is a lot of content, increase buffer size
|
||||
}, (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(stdout);
|
||||
});
|
||||
const output = await execHelper('Get-Command -All | Select-Object Name, CommandType, DisplayName, Definition | ConvertTo-Json', {
|
||||
...options,
|
||||
maxBuffer: 1024 * 1024 * 100 // This is a lot of content, increase buffer size
|
||||
});
|
||||
let json: any;
|
||||
try {
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import type { ICompletionResource } from '../types';
|
||||
import { exec, spawn, type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
import { execHelper, spawnHelper } from './common';
|
||||
import { type ExecOptionsWithStringEncoding } from 'node:child_process';
|
||||
|
||||
export async function getZshGlobals(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<(string | ICompletionResource)[]> {
|
||||
return [
|
||||
@@ -15,15 +16,7 @@ export async function getZshGlobals(options: ExecOptionsWithStringEncoding, exis
|
||||
}
|
||||
|
||||
async function getBuiltins(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<string[]> {
|
||||
const compgenOutput = await new Promise<string>((resolve, reject) => {
|
||||
exec('printf "%s\\n" ${(k)builtins}', options, (error, stdout) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
const compgenOutput = await execHelper('printf "%s\\n" ${(k)builtins}', options);
|
||||
const filter = (cmd: string) => cmd && !existingCommands?.has(cmd);
|
||||
return compgenOutput.split('\n').filter(filter);
|
||||
}
|
||||
@@ -33,21 +26,7 @@ async function getAliases(options: ExecOptionsWithStringEncoding): Promise<IComp
|
||||
// be set up. Note that this could differ from the actual aliases as it's a new bash
|
||||
// session, for the same reason this would not include aliases that are created
|
||||
// by simply running `alias ...` in the terminal.
|
||||
const aliasOutput = await new Promise<string>((resolve, reject) => {
|
||||
const child = spawn('zsh', ['-ic', 'alias'], options);
|
||||
let stdout = '';
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(`zsh process exited with code ${code}`));
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const aliasOutput = await spawnHelper('zsh', ['-ic', 'alias'], options);
|
||||
const result: ICompletionResource[] = [];
|
||||
for (const line of aliasOutput.split('\n')) {
|
||||
const match = line.match(/^(?<alias>[a-zA-Z0-9\.:-]+)=(?:'(?<resolved>.+)'|(?<resolved>.+))$/);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs/promises';
|
||||
import * as path from 'path';
|
||||
import { exec, ExecOptionsWithStringEncoding } from 'child_process';
|
||||
import { ExecOptionsWithStringEncoding } from 'child_process';
|
||||
import { upstreamSpecs } from './constants';
|
||||
import codeCompletionSpec from './completions/code';
|
||||
import cdSpec from './completions/cd';
|
||||
|
||||
Reference in New Issue
Block a user