Sign in

    pty

    Cross-platform PTY (pseudo-terminal) spawning for MoonBit native targets, integrated with moonbitlang/async.

    pty
    pseudo-terminal
    async
    native
    Download zip
    Version
    0.4.1
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    38K

    #moonbit-community/pty

    Cross-platform PTY (pseudo-terminal) spawning for MoonBit native targets, integrated with moonbitlang/async so reads and writes go through the async event loop instead of blocking the thread.

    #API

    @async.with_task_group(group => {
    let pty = @pty.spawn(
    group,
    "sh", ["-c", "echo hello"],
    rows=24, cols=80,
    cwd="/workspace",
    )
    let text = pty.read_all().text() // Pty implements @io.Reader
    pty.write(b"ls\n") // ... and @io.Writer
    pty.resize(rows=40, cols=120)
    let pid : Int = pty.pid()
    let exit_code : Int = pty.wait()
    })

    The pty's resources are released when the task group exits. On cancellation the child gets a 5 s grace period, then a hard kill. Pty::wait returns the child's exit code; call it explicitly when the exit code matters.

    By default the task group waits for the child to exit. Pass no_wait=true (same semantics as @async/process.spawn) to let the group exit as soon as its own tasks are done, terminating the child instead of waiting for it.

    #Drain the pty concurrently

    Do not wait() first and read() afterwards. A pty master is a bounded kernel queue, and on macOS the kernel discards whatever is still queued a few hundred milliseconds after the child exits. Read concurrently while waiting; reading late yields a clean but empty EOF.

    Relatedly, ConPTY output is a screen rendering, not a byte stream: expect VT escape sequences (including an initial clear-screen) surrounding your child's output. Strip or escape them before asserting on pty output in tests — a failing diff that prints raw pty output replays those sequences into your terminal.

    #Further reading

    • docs/internals.md — executable resolution, environment merging, and platform architecture: unix fork/execve, Windows ConPTY startup, argv encoding.
    • docs/invariants.md — hard-won debugging conclusions and decision records that must not regress.

    Pty

    type Pty

    impl Reader for Pty
    impl Writer for Pty

    Pty::drop

    async fn Pty::drop(self : Pty, len : Int) -> Int

    Pty::pid

    fn Pty::pid(self : Pty) -> Int

    Pty::read

    async fn Pty::read(self : Pty, dst : FixedArray[Byte], offset? : Int, max_len? : Int) -> Int

    Pty::read_all

    async fn Pty::read_all(self : Pty) -> &
    Data

    Pty::read_exactly

    async fn Pty::read_exactly(self : Pty, len : Int) -> Bytes

    Pty::read_some

    async fn Pty::read_some(self : Pty, max_len? : Int) -> Bytes?

    Pty::read_until

    async fn Pty::read_until(self : Pty, sep : StringView) -> String?

    Pty::resize

    fn Pty::resize(self : Pty, rows~ : Int, cols~ : Int) -> Unit raise
    OSError

    Pty::wait

    async fn Pty::wait(self : Pty) -> Int

    Pty::write

    async fn Pty::write(self : Pty, data : &
    Data
    ) -> Unit

    Pty::write_once

    async fn Pty::write_once(self : Pty, buf : Bytes, offset~ : Int, len~ : Int) -> Int

    Pty::write_reader

    async fn Pty::write_reader(self : Pty, reader : &
    Reader
    ) -> Unit

    spawn

    async fn[X] spawn(group :
    TaskGroup
    [X], rows? : Int, cols? : Int, file : StringView, args : ArrayView[StringView], extra_env? : Map[String, String], inherit_env? : Bool, cwd? : StringView, no_wait? : Bool) -> Pty