import { type MergeableRecord } from '../util/objects';
import type { SemVer } from 'semver';
import type { AsyncOrSync } from 'ts-essentials';
import type { RShellEngineConfig } from '../config';
import type { AsyncParser } from './parser';
import type { RParseRequest } from './retriever';
export type OutputStreamSelector = 'stdout' | 'stderr' | 'both';
export interface CollectorTimeout extends MergeableRecord {
    /**
   * number of milliseconds to wait for the collection to finish
   */
    ms: number;
    resetOnNewData: boolean;
    /**
     * invoked when the timeout is reached. If not set, the promise will be rejected with an error.
     */
    onTimeout?: (resolve: (value: AsyncOrSync<string[]>) => void, reject: (value: AsyncOrSync<string[]>) => void, partialResult: string[]) => void;
}
/**
 * Configuration for the internal output collector used by the {@link RShell}
 * The defaults are configured with {@link DEFAULT_OUTPUT_COLLECTOR_CONFIGURATION}
 */
export interface OutputCollectorConfiguration extends MergeableRecord {
    /** the streams to use to collect the output from */
    from: OutputStreamSelector;
    /**
   * a string marker to signal that the command was executed successfully.
   * must not appear as a standalone line in the output. this is our hacky way of ensuring that we are done.
   */
    postamble: string;
    /** internal timeout configuration to use (see {@link CollectorTimeout}) */
    timeout: CollectorTimeout;
    /** should the postamble be included in the result? */
    keepPostamble: boolean;
    /** automatically trim all lines in the output (useful to ignore trailing whitespace etc.) */
    automaticallyTrimOutput: boolean;
}
export declare const DEFAULT_OUTPUT_COLLECTOR_CONFIGURATION: OutputCollectorConfiguration;
export declare const enum RShellReviveOptions {
    Never = 0,
    OnError = 1,
    Always = 2
}
export interface RShellExecutionOptions extends MergeableRecord {
    /** The path to the R executable, can be only the executable if it is to be found on the PATH. */
    readonly pathToRExecutable: string;
    /** Command line options to use when starting the R session. */
    readonly commandLineOptions: readonly string[];
    /** The current working directory of the R session. */
    readonly cwd: string;
    /** The character to use to mark the end of a line. Is probably always `\n` (even on windows). */
    readonly eol: string;
    /** The environment variables available in the R session. */
    readonly env: NodeJS.ProcessEnv | undefined;
    /** The path to the library directory, use undefined to let R figure that out for itself */
    readonly homeLibPath: string | undefined;
}
export interface RShellSessionOptions extends RShellExecutionOptions {
    /** If set, the R session will be restarted if it exits due to an error */
    readonly revive: RShellReviveOptions;
    /** Called when the R session is restarted, this makes only sense if `revive` is not set to `'never'` */
    readonly onRevive: (code: number, signal: string | null) => void;
}
/**
 * Configuration of an {@link RShell} instance.
 * See {@link DEFAULT_R_SHELL_OPTIONS} for the default values used by {@link RShell}.
 */
export interface RShellOptions extends RShellSessionOptions {
    readonly sessionName: string;
}
export declare const DEFAULT_R_PATH: string;
export declare function getDefaultRShellOptions(config?: RShellEngineConfig): RShellOptions;
/**
 * The `RShell` represents an interactive session with the R interpreter.
 * You can configure it by {@link RShellOptions}.
 *
 * At the moment we are using a live R session (and not networking etc.) to communicate with R easily,
 * which allows us to install packages etc. However, this might and probably will change in the future
 * (leaving this as a legacy mode :D)
 */
export declare class RShell implements AsyncParser<string> {
    readonly name = "r-shell";
    readonly async = true;
    readonly options: Readonly<RShellOptions>;
    private session;
    private readonly log;
    private versionCache;
    private tempDirs;
    constructor(config?: RShellEngineConfig, options?: Partial<RShellOptions>);
    parse(request: RParseRequest): Promise<string>;
    private revive;
    /**
     * sends the given command directly to the current R session
     * will not do anything to alter input markers!
     */
    sendCommand(command: string): void;
    rVersion(): Promise<string | 'unknown' | 'none'>;
    usedRVersion(): Promise<SemVer | null>;
    injectLibPaths(...paths: readonly string[]): void;
    tryToInjectHomeLibPath(): void;
    /**
     * checks if a given package is already installed on the system!
     */
    isPackageInstalled(packageName: string): Promise<boolean>;
    /**
   * Send a command and collect the output
   *
   * @param command     - The R command to execute (similar to {@link sendCommand})
   * @param addonConfig - Further configuration on how and what to collect: see {@link OutputCollectorConfiguration},
   *                      defaults are set in {@link DEFAULT_OUTPUT_COLLECTOR_CONFIGURATION}
   */
    sendCommandWithOutput(command: string, addonConfig?: Partial<OutputCollectorConfiguration>): Promise<string[]>;
    /**
   * execute multiple commands in order
   *
   * @see sendCommand
   */
    sendCommands(...commands: readonly string[]): void;
    /**
   * clears the R environment using the `rm` command.
   */
    clearEnvironment(): void;
    /**
     * Obtain the temporary directory used by R.
     * Additionally, this marks the directory for removal when the shell exits.
     */
    obtainTmpDir(): Promise<string>;
    /**
   * Close the current R session, makes the object effectively invalid (can no longer be reopened etc.)
   *
   * @returns true if the operation succeeds, false otherwise
   */
    close(): boolean;
    private _sendCommand;
}
