tastty 0.1.0

Embeddable pseudoterminal sessions for Rust applications
//! Unmanaged-session path: caller-supplied reader / writer streams.

use std::io::{Read, Write};

use crate::error::Result;

use super::SessionOptions;
use super::Terminal;
use super::Unmanaged;
use super::build_common;

impl Terminal<Unmanaged> {
    /// Create a session from pre-opened reader/writer streams.
    ///
    /// Use this when you manage the PTY and child process yourself
    /// (e.g., custom fork/exec, Docker, serial ports, SSH channels).
    ///
    /// The session takes ownership of the reader and writer. It will NOT
    /// manage the child process lifecycle or send signals on Drop.
    ///
    /// # Errors
    ///
    /// Returns [`Error::ThreadSpawn`](crate::Error::ThreadSpawn) if the
    /// reader or writer background thread cannot be started.
    ///
    /// [`tastty_core::Error`]: tastty_core::Error
    ///
    /// # Example
    ///
    /// ```no_run
    /// use tastty::{SessionOptions, Terminal, Unmanaged};
    ///
    /// # fn example(reader: Box<dyn std::io::Read + Send>, writer: Box<dyn std::io::Write + Send>) {
    /// let session: Terminal<Unmanaged> = Terminal::from_reader_writer(
    ///     reader,
    ///     writer,
    ///     SessionOptions::default(),
    /// ).unwrap();
    ///
    /// let contents = session.with_screen(|s| s.contents());
    /// # }
    /// ```
    pub fn from_reader_writer(
        reader: Box<dyn Read + Send>,
        writer: Box<dyn Write + Send>,
        mut opts: SessionOptions,
    ) -> Result<Self> {
        let common = build_common(reader, writer, &mut opts, None)?;

        Ok(Self {
            parser: common.parser,
            writer_tx: Some(common.writer_tx),
            managed: None,
            reader_handle: Some(common.reader_handle),
            writer_handle: Some(common.writer_handle),
            dirty: common.dirty,
            redraw_notify: common.redraw_notify,
            event_rx: std::sync::Mutex::new(Some(common.event_rx)),
            io_error_rx: std::sync::Mutex::new(Some(common.io_error_rx)),
            last_sync_arrival_ms: common.last_sync_arrival_ms,
            epoch: common.epoch,
            virtual_cols: common.virtual_cols,
            key_callback: common.key_callback,
            _mode: std::marker::PhantomData,
        })
    }
}