use std::ffi::OsStr;
use std::fmt;
use std::os::windows::io::{AsHandle, BorrowedHandle};
use std::path::Path;
use super::pty::Pty;
use super::session::Session;
use crate::core::child::ChildCore;
use crate::core::session;
use crate::error::Result;
use crate::status::ExitStatus;
use crate::SessionOptions;
#[derive(Debug)]
pub struct Command {
inner: crate::command::Command,
}
impl Command {
#[must_use]
pub fn new(program: impl AsRef<OsStr>) -> Self {
Self {
inner: crate::command::Command::new(program),
}
}
pub fn arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
self.inner.arg(arg);
self
}
pub fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
self.inner.args(args);
self
}
pub fn raw_arg(&mut self, text: impl AsRef<OsStr>) -> &mut Self {
self.inner.raw_arg(text);
self
}
pub fn env(&mut self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Self {
self.inner.env(key, value);
self
}
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
self.inner.envs(vars);
self
}
pub fn env_remove(&mut self, key: impl AsRef<OsStr>) -> &mut Self {
self.inner.env_remove(key);
self
}
pub fn env_clear(&mut self) -> &mut Self {
self.inner.env_clear();
self
}
pub fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self {
self.inner.current_dir(dir);
self
}
#[cfg(test)]
pub(crate) fn kill_on_drop(&mut self, kill: bool) -> &mut Self {
self.inner.kill_on_drop(kill);
self
}
pub fn spawn(&mut self) -> Result<Session> {
self.spawn_with(SessionOptions::default())
}
pub fn spawn_with(&mut self, options: SessionOptions) -> Result<Session> {
let (size, backend) = options.into_parts();
let mut builder = Pty::builder().size(size);
if let Some(backend) = backend {
builder = builder.backend(backend);
}
let pty = builder.build()?;
let child = self.spawn_in_with_policy(&pty, true)?;
let controller = pty.controller();
let (output, input) = pty.into_split();
Ok(Session::new(child, output, input, controller))
}
#[cfg(test)]
pub(crate) fn spawn_in(&mut self, pty: &Pty) -> Result<Child> {
self.spawn_in_with_policy(pty, self.inner.get_kill_on_drop())
}
fn spawn_in_with_policy(&mut self, pty: &Pty, kill_on_drop: bool) -> Result<Child> {
let root = session::spawn_root(&pty.inner, &mut self.inner, kill_on_drop)?;
Ok(Child {
core: ChildCore::from_root(root),
})
}
}
pub struct Child {
core: ChildCore,
}
impl fmt::Debug for Child {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.core.fmt(f)
}
}
impl Child {
#[must_use]
pub const fn id(&self) -> u32 {
self.core.id()
}
pub fn wait(&mut self) -> Result<ExitStatus> {
self.core.wait_blocking()
}
pub fn try_wait(&mut self) -> Result<Option<ExitStatus>> {
self.core.try_wait()
}
pub fn kill(&mut self) -> Result<()> {
self.core.kill()
}
}
impl AsHandle for Child {
fn as_handle(&self) -> BorrowedHandle<'_> {
self.core.as_handle()
}
}
#[cfg(doctest)]
mod api_boundary {}