radicle-cli 0.20.0

Radicle CLI
Documentation
use std::io;
use std::process::{Command, Stdio};

use radicle_term::element;
use radicle_term::{Constraint, Element};

use crate::terminal;

/// Output the given element through a pager, if necessary.
/// If it fits within the screen, don't run it through a pager.
pub fn run(elem: impl Element) -> io::Result<()> {
    let Some(constraint) = Constraint::from_env() else {
        return elem.write(Constraint::UNBOUNDED);
    };
    let Some(rows) = terminal::rows() else {
        return elem.write(Constraint::UNBOUNDED);
    };
    if elem.size(Constraint::UNBOUNDED).rows <= rows {
        return elem.write(Constraint::UNBOUNDED);
    }
    let Some(pager) = radicle::profile::env::pager() else {
        return elem.write(Constraint::UNBOUNDED);
    };

    #[cfg(unix)]
    let Some(parts) = shlex::split(&pager) else {
        return elem.write(Constraint::UNBOUNDED);
    };
    #[cfg(windows)]
    let parts = winsplit::split(&pager);

    let Some((program, args)) = parts.split_first() else {
        return elem.write(Constraint::UNBOUNDED);
    };

    let mut child = Command::new(program)
        .stdin(Stdio::piped())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .args(args)
        .spawn()?;

    let writer = child.stdin.as_mut().unwrap();
    let result = element::write_to(&elem, writer, constraint);

    child.wait()?;

    match result {
        // This error is expected when the pager is exited.
        Err(e) if e.kind() == io::ErrorKind::BrokenPipe => {}
        Err(e) => return Err(e),
        Ok(_) => {}
    }

    Ok(())
}