rust_pty/lib.rs
1//! rust-pty: Cross-platform async PTY library
2//!
3//! This crate provides a unified async interface for pseudo-terminal (PTY) operations
4//! across Unix (Linux, macOS) and Windows (`ConPTY`) platforms.
5//!
6//! # Platform Support
7//!
8//! - **Unix**: Uses `rustix` for PTY allocation and process management
9//! - **Windows**: Uses `ConPTY` via `windows-sys` (Windows 10 1809+)
10//!
11//! # Quick Start
12//!
13//! ```ignore
14//! use rust_pty::{NativePtySystem, PtySystem, PtyConfig};
15//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
16//!
17//! #[tokio::main]
18//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
19//! let config = PtyConfig::default();
20//! let (mut master, mut child) = NativePtySystem::spawn_shell(&config).await?;
21//!
22//! // Write a command
23//! master.write_all(b"echo hello\n").await?;
24//!
25//! // Read output
26//! let mut buf = [0u8; 1024];
27//! let n = master.read(&mut buf).await?;
28//! println!("{}", String::from_utf8_lossy(&buf[..n]));
29//!
30//! // Clean up
31//! child.kill()?;
32//! Ok(())
33//! }
34//! ```
35//!
36//! # Features
37//!
38//! - **Async I/O**: First-class async support with Tokio
39//! - **Cross-platform**: Single API for Unix and Windows
40//! - **Type-safe**: Strong typing with proper error handling
41//! - **Zero-copy**: Efficient buffer management for high-throughput scenarios
42
43pub mod config;
44pub mod error;
45pub mod traits;
46
47#[cfg(unix)]
48pub mod unix;
49
50#[cfg(windows)]
51pub mod windows;
52
53// Re-export primary types
54pub use config::{PtyConfig, PtyConfigBuilder, PtySignal, WindowSize};
55pub use error::{PtyError, Result};
56pub use traits::{ExitStatus, PtyChild, PtyMaster, PtySystem};
57// Platform-specific re-exports
58#[cfg(unix)]
59pub use unix::{NativePtySystem, UnixPtyChild, UnixPtyMaster, UnixPtySystem};
60#[cfg(windows)]
61pub use windows::{NativePtySystem, WindowsPtyChild, WindowsPtyMaster, WindowsPtySystem};
62
63/// Create a PTY with the default configuration and spawn a shell.
64///
65/// This is a convenience function that uses the platform's native PTY system.
66///
67/// # Errors
68///
69/// Returns an error if PTY creation or shell spawning fails.
70#[cfg(unix)]
71pub async fn spawn_shell() -> Result<(UnixPtyMaster, UnixPtyChild)> {
72 UnixPtySystem::spawn_shell(&PtyConfig::default()).await
73}
74
75/// Create a PTY with the default configuration and spawn a shell.
76///
77/// This is a convenience function that uses the platform's native PTY system.
78///
79/// # Errors
80///
81/// Returns an error if PTY creation or shell spawning fails.
82#[cfg(windows)]
83pub async fn spawn_shell() -> Result<(WindowsPtyMaster, WindowsPtyChild)> {
84 WindowsPtySystem::spawn_shell(&PtyConfig::default()).await
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn default_config() {
93 let config = PtyConfig::default();
94 assert_eq!(config.window_size, (80, 24));
95 assert!(config.new_session);
96 }
97
98 #[test]
99 fn window_size_conversion() {
100 let size = WindowSize::new(120, 40);
101 assert_eq!(size.cols, 120);
102 assert_eq!(size.rows, 40);
103 }
104
105 #[cfg(unix)]
106 #[tokio::test]
107 async fn spawn_echo() {
108 let config = PtyConfig::default();
109 let result = UnixPtySystem::spawn("echo", ["test"], &config).await;
110
111 // May fail in some CI environments
112 if let Ok((mut master, mut child)) = result {
113 let _ = child.wait().await;
114 master.close().ok();
115 }
116 }
117}