<commit_before>import * as ChildProcess from "child_process";
import * as OS from "os";
import * as _ from "lodash";
import {baseName, resolveFile, exists, filterAsync, shell} from "./utils/Common";
const ptyInternalPath = require.resolve("./PTYInternal");

interface Message {
    data?: string;
    exit?: number;
}

export default class PTY {
    private process: ChildProcess.ChildProcess;

    // TODO: write proper signatures.
    // TODO: use generators.
    // TODO: terminate. https://github.com/atom/atom/blob/v1.0.15/src/task.coffee#L151
    constructor(command: string, args: string[], env: ProcessEnvironment, dimensions: Dimensions, dataHandler: (d: string) => void, exitHandler: (c: number) => void) {
        this.process = ChildProcess.fork(
            ptyInternalPath,
            [command, dimensions.columns.toString(), dimensions.rows.toString(), ...args],
            {env: env, cwd: env.PWD}
        );

        this.process.on("message", (message: Message) => {
            if (message.hasOwnProperty("data")) {
                dataHandler(message.data);
            } else if (message.hasOwnProperty("exit")) {
                exitHandler(message.exit);
                this.process.disconnect();
            } else {
                throw `Unhandled message: ${JSON.stringify(message)}`;
            }
        });
    }

    write(data: string): void {
        this.process.send({input: data});
    }

    set dimensions(dimensions: Dimensions) {
        this.process.send({resize: [dimensions.columns, dimensions.rows]});
    }

    kill(signal: string): void {
        this.process.send({signal: signal});
    }
}

export function executeCommand(command: string, args: string[] = [], directory: string): Promise<string> {
    return new Promise((resolve, reject) => {
        ChildProcess.exec(`${command} ${args.join(" ")}`, { env: _.extend({PWD: directory}, process.env)}, (error, output) => {
            if (error) {
                reject();
            } else {
                resolve(output);
            }
        });
    });
}

export async function linedOutputOf(command: string, args: string[], directory: string): Promise<string[]> {
    let output = await executeCommand(command, args, directory);
    return output.split(OS.EOL).filter(path => path.length > 0);
}

export async function executeCommandWithShellConfig(command: string): Promise<string[]> {
    const shellName = baseName(shell());
    const sourceCommands = (await existingConfigFiles(shellName)).map(fileName => `source ${fileName}`);

    return await linedOutputOf(shell(), ["-c", `'${[...sourceCommands, command].join("; ")}'`], process.env.HOME);
}

async function existingConfigFiles(shellName: string): Promise<string[]> {
    const resolvedConfigFiles = configFiles(shellName).map(fileName => resolveFile(process.env.HOME, fileName));
    return await filterAsync(resolvedConfigFiles, exists);
}

function configFiles(shellName: string): string[] {
    switch (shellName) {
        case "zsh":
            return ["~/.zshrc", "~/.zsh_profile"];
        case "bash":
            return ["~/.bashrc", "~/.bash_profile"];
        default:
            throw `Unknown shell: ${shellName}`;
    }
}
<commit_msg>Specify cwd for executeCommand since $PWD isn't understood by sh.<commit_after>import * as ChildProcess from "child_process";
import * as OS from "os";
import * as _ from "lodash";
import {baseName, resolveFile, exists, filterAsync, shell} from "./utils/Common";
const ptyInternalPath = require.resolve("./PTYInternal");

interface Message {
    data?: string;
    exit?: number;
}

export default class PTY {
    private process: ChildProcess.ChildProcess;

    // TODO: write proper signatures.
    // TODO: use generators.
    // TODO: terminate. https://github.com/atom/atom/blob/v1.0.15/src/task.coffee#L151
    constructor(command: string, args: string[], env: ProcessEnvironment, dimensions: Dimensions, dataHandler: (d: string) => void, exitHandler: (c: number) => void) {
        this.process = ChildProcess.fork(
            ptyInternalPath,
            [command, dimensions.columns.toString(), dimensions.rows.toString(), ...args],
            {env: env, cwd: env.PWD}
        );

        this.process.on("message", (message: Message) => {
            if (message.hasOwnProperty("data")) {
                dataHandler(message.data);
            } else if (message.hasOwnProperty("exit")) {
                exitHandler(message.exit);
                this.process.disconnect();
            } else {
                throw `Unhandled message: ${JSON.stringify(message)}`;
            }
        });
    }

    write(data: string): void {
        this.process.send({input: data});
    }

    set dimensions(dimensions: Dimensions) {
        this.process.send({resize: [dimensions.columns, dimensions.rows]});
    }

    kill(signal: string): void {
        this.process.send({signal: signal});
    }
}

export function executeCommand(command: string, args: string[] = [], directory: string): Promise<string> {
    return new Promise((resolve, reject) => {
        const options = {
            env: _.extend({PWD: directory}, process.env),
            cwd: directory,
        };

        ChildProcess.exec(`${command} ${args.join(" ")}`, options, (error, output) => {
            if (error) {
                reject();
            } else {
                resolve(output);
            }
        });
    });
}

export async function linedOutputOf(command: string, args: string[], directory: string): Promise<string[]> {
    let output = await executeCommand(command, args, directory);
    return output.split(OS.EOL).filter(path => path.length > 0);
}

export async function executeCommandWithShellConfig(command: string): Promise<string[]> {
    const shellName = baseName(shell());
    const sourceCommands = (await existingConfigFiles(shellName)).map(fileName => `source ${fileName}`);

    return await linedOutputOf(shell(), ["-c", `'${[...sourceCommands, command].join("; ")}'`], process.env.HOME);
}

async function existingConfigFiles(shellName: string): Promise<string[]> {
    const resolvedConfigFiles = configFiles(shellName).map(fileName => resolveFile(process.env.HOME, fileName));
    return await filterAsync(resolvedConfigFiles, exists);
}

function configFiles(shellName: string): string[] {
    switch (shellName) {
        case "zsh":
            return ["~/.zshrc", "~/.zsh_profile"];
        case "bash":
            return ["~/.bashrc", "~/.bash_profile"];
        default:
            throw `Unknown shell: ${shellName}`;
    }
}

{'fraction_non_alphanumeric': 0.1513677811550152, 'fraction_numerical': 0.0024316109422492403, 'mean_word_length': 2.8689006466784246, 'pattern_counts': {'":': 4, '<': 11, '<?xml version=': 0, '>': 29, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4836981', 'n_tokens_mistral': 1855, 'n_tokens_neox': 1824, 'n_words': 434}