#![allow(dead_code)]
use std::io::{IsTerminal, Write};
use std::process::{Command, Stdio};
use std::sync::Arc;
use rich_rust::console::Console;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PagerResult {
Paged,
Inline,
}
pub struct PagerConfig {
pub interactive_allowed: bool,
pub force_pager: bool,
}
pub fn page_content(content: &str, console: &Arc<Console>, cfg: &PagerConfig) -> PagerResult {
if !cfg.interactive_allowed {
console.print(content);
return PagerResult::Inline;
}
if !std::io::stdout().is_terminal() {
console.print(content);
return PagerResult::Inline;
}
let args = if cfg.force_pager {
vec!["-R", "-X"]
} else {
vec!["-R", "-F", "-X"]
};
let pager_result = Command::new("less")
.args(&args)
.stdin(Stdio::piped())
.spawn();
match pager_result {
Ok(mut child) => {
if let Some(mut stdin) = child.stdin.take() {
if stdin.write_all(content.as_bytes()).is_ok() {
drop(stdin); if child.wait().is_ok() {
return PagerResult::Paged;
}
}
}
console.print(content);
PagerResult::Inline
}
Err(_) => {
console.print(content);
PagerResult::Inline
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pager_result_variants() {
assert_ne!(PagerResult::Paged, PagerResult::Inline);
}
#[test]
fn non_interactive_falls_back_to_inline() {
let console = Console::builder().force_terminal(false).build().shared();
let cfg = PagerConfig {
interactive_allowed: false,
force_pager: false,
};
let result = page_content("test content", &console, &cfg);
assert_eq!(result, PagerResult::Inline);
}
}