saya_cli/commands/
output.rs1use crate::render::{RenderFormat, TerminalEvent, render_event};
2use saya_types::ConnectionError;
3use std::cell::RefCell;
4
5thread_local! {
11 static CAPTURE: RefCell<Option<(String, String)>> = const { RefCell::new(None) };
12}
13
14pub fn emit(event: TerminalEvent, format: RenderFormat) {
15 let rendered = render_event(&event, format);
16 CAPTURE.with(|cell| match cell.borrow_mut().as_mut() {
17 Some((stdout, stderr)) => {
18 stdout.push_str(&rendered.stdout);
19 stderr.push_str(&rendered.stderr);
20 }
21 None => {
22 print!("{}", rendered.stdout);
23 eprint!("{}", rendered.stderr);
24 }
25 });
26}
27
28pub fn capture_output_start() {
32 CAPTURE.with(|cell| {
33 let mut slot = cell.borrow_mut();
34 assert!(
35 slot.is_none(),
36 "capture_output_start called without a matching capture_output_take"
37 );
38 *slot = Some((String::new(), String::new()));
39 });
40}
41
42pub fn capture_output_take() -> (String, String) {
45 CAPTURE.with(|cell| {
46 cell.borrow_mut()
47 .take()
48 .expect("capture_output_take called without a matching capture_output_start")
49 })
50}
51
52pub fn result(message: String, format: RenderFormat) -> Result<i32, Box<dyn std::error::Error>> {
53 emit(TerminalEvent::Result { message }, format);
54 Ok(0)
55}
56
57pub fn failure(
58 code: i32,
59 error: ConnectionError,
60 format: RenderFormat,
61) -> Result<i32, Box<dyn std::error::Error>> {
62 emit(
63 TerminalEvent::Error {
64 message: error.to_string(),
65 },
66 format,
67 );
68 Ok(code)
69}
70
71pub fn failure_message(
72 code: i32,
73 message: String,
74 format: RenderFormat,
75) -> Result<i32, Box<dyn std::error::Error>> {
76 emit(TerminalEvent::Error { message }, format);
77 Ok(code)
78}