src/utils/utils.ts (78 lines of code) (raw):
import * as vscode from 'vscode'
import * as path from 'path'
import {promisify} from 'util'
import {exec} from 'child_process'
import * as fs from 'fs/promises'
import * as zlib from 'zlib'
const execAsync = promisify(exec)
// Escape codes, compiled from https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
// Plus additional markers for custom `\x1b]...\x07` instructions.
// Borrowed from VS Code base (see: https://github.com/Microsoft/vscode/blob/main/src/vs/base/common/strings.ts)
const CSI_SEQUENCE =
// eslint-disable-next-line no-control-regex
/(:?(:?\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~])|(:?\x1b\].*?\x07)/g
export enum ANSI_CODES {
RED = '\u001b[31m',
CYAN = '\u001b[36m',
BOLD = '\u001b[1m',
RESET = '\u001b[0m',
}
export class Utils {
static getWorkspaceRoot(): vscode.Uri | null {
if (
vscode.workspace.workspaceFolders === undefined ||
vscode.workspace.workspaceFolders?.length == 0
) {
return null
}
if (
!vscode.workspace.workspaceFile ||
vscode.workspace.workspaceFile?.scheme === 'untitled'
) {
return vscode.workspace.workspaceFolders[0].uri
}
return vscode.Uri.parse(
path.dirname(vscode.workspace.workspaceFile.toString())
)
}
static async getGitRootFromPath(fsPath: string): Promise<string | null> {
const {stdout} = await execAsync('git rev-parse --show-toplevel', {
cwd: fsPath,
})
return stdout.trim()
}
static async getWorkspaceGitRoot(): Promise<string | null> {
const workspaceRoot = Utils.getWorkspaceRoot()
if (!workspaceRoot) {
return null
}
return Utils.getGitRootFromPath(workspaceRoot.fsPath)
}
static async gunzip(data: Buffer): Promise<Buffer> {
return new Promise((resolve, reject) => {
zlib.gunzip(data, (err, result) => {
if (err) reject(err)
else resolve(result)
})
})
}
// Use wrapped file i/o operations for use in stubbing.
static async readdir(path: string): Promise<string[]> {
return fs.readdir(path)
}
static async readFile(path: string): Promise<string> {
return fs.readFile(path, 'utf8')
}
/**
* Strips ANSI escape sequences from a string.
* Borrowed from VS Code base (see: https://github.com/Microsoft/vscode/blob/main/src/vs/base/common/strings.ts)
* @param str The string to strip the ANSI escape sequences from.
*
* @example
* removeAnsiEscapeCodes('\u001b[31mHello, World!\u001b[0m');
* // 'Hello, World!'
*/
static removeAnsiEscapeCodes(str: string): string {
if (str) {
str = str.replace(CSI_SEQUENCE, '')
}
return str
}
}
export class Deferred<T> {
public promise: Promise<T>
public resolve!: (value: T | PromiseLike<T>) => void
public reject!: (reason?: any) => void
constructor() {
this.promise = new Promise<T>((resolve, reject) => {
this.resolve = resolve
this.reject = reject
})
}
}