mod winpty;
mod conpty;
mod base;
use std::ffi::OsString;
use std::default::Default;
use self::winpty::WinPTY;
pub use self::winpty::{MouseMode, AgentConfig};
use self::conpty::ConPTY;
pub use base::{PTYImpl, PTYProcess};
#[derive(Primitive)]
#[derive(Copy, Clone, Debug)]
pub enum PTYBackend {
ConPTY = 0,
WinPTY = 1,
Auto = 2,
NoBackend = 3,
}
#[derive(Clone, Debug)]
pub struct PTYArgs {
pub cols: i32,
pub rows: i32,
pub mouse_mode: MouseMode,
pub timeout: u32,
pub agent_config: AgentConfig
}
impl Default for PTYArgs {
fn default() -> Self {
Self {
cols: 80,
rows: 24,
mouse_mode: MouseMode::WINPTY_MOUSE_MODE_NONE,
timeout: 10000,
agent_config: AgentConfig::WINPTY_FLAG_COLOR_ESCAPES
}
}
}
pub struct PTY {
backend: PTYBackend,
pty: Box<dyn PTYImpl>
}
impl PTY {
pub fn new(args: &PTYArgs) -> Result<PTY, OsString> {
let mut errors: OsString = OsString::from("There were some errors trying to instantiate a PTY:");
let conpty_instance: Result<Box<dyn PTYImpl>, OsString> = ConPTY::new(args);
let pty: Option<PTY> =
match conpty_instance {
Ok(conpty) => {
let pty_instance = PTY {
backend: PTYBackend::ConPTY,
pty: conpty
};
Some(pty_instance)
},
Err(err) => {
errors = OsString::from(format!("{:?} (ConPTY) -> {:?};", errors, err));
None
}
};
match pty {
Some(pty) => Ok(pty),
None => {
let winpty_instance: Result<Box<dyn PTYImpl>, OsString> = WinPTY::new(args);
match winpty_instance {
Ok(winpty) => {
let pty_instance = PTY {
backend: PTYBackend::WinPTY,
pty: winpty
};
Ok(pty_instance)
},
Err(err) => {
errors = OsString::from(format!("{:?} (WinPTY) -> {:?}", errors, err));
Err(errors)
}
}
}
}
}
pub fn new_with_backend(args: &PTYArgs, backend: PTYBackend) -> Result<PTY, OsString> {
match backend {
PTYBackend::ConPTY => {
match ConPTY::new(args) {
Ok(conpty) => {
let pty = PTY {
backend,
pty: conpty
};
Ok(pty)
},
Err(err) => Err(err)
}
},
PTYBackend::WinPTY => {
match WinPTY::new(args) {
Ok(winpty) => {
let pty = PTY {
backend,
pty: winpty
};
Ok(pty)
},
Err(err) => Err(err)
}
},
PTYBackend::Auto => PTY::new(args),
PTYBackend::NoBackend => Err(OsString::from("NoBackend is not a valid option"))
}
}
pub fn spawn(&mut self, appname: OsString, cmdline: Option<OsString>, cwd: Option<OsString>, env: Option<OsString>) -> Result<bool, OsString> {
self.pty.spawn(appname, cmdline, cwd, env)
}
pub fn set_size(&self, cols: i32, rows: i32) -> Result<(), OsString> {
self.pty.set_size(cols, rows)
}
pub fn get_backend(&self) -> PTYBackend {
self.backend
}
pub fn read(&self, blocking: bool) -> Result<OsString, OsString> {
self.pty.read(blocking)
}
pub fn write(&self, buf: OsString) -> Result<u32, OsString> {
self.pty.write(buf)
}
pub fn is_eof(&self) -> Result<bool, OsString> {
self.pty.is_eof()
}
pub fn get_exitstatus(&self) -> Result<Option<u32>, OsString> {
self.pty.get_exitstatus()
}
pub fn is_alive(&self) -> Result<bool, OsString> {
self.pty.is_alive()
}
pub fn get_pid(&self) -> u32 {
self.pty.get_pid()
}
pub fn get_fd(&self) -> isize {
self.pty.get_fd()
}
pub fn wait_for_exit(&self) -> Result<bool, OsString> {
self.pty.wait_for_exit()
}
pub fn cancel_io(&self) -> Result<bool, OsString> {
self.pty.cancel_io()
}
}