1mod ask;
4mod human;
5pub(crate) mod json;
6mod obsidian;
7mod recall;
8mod search;
9mod style;
10
11use crate::exit_codes;
12use eyre::Result;
13use std::io::{self, Write};
14use talon_core::TalonEnvelope;
15
16pub use ask::format_ask_human;
17pub use human::{format_inspect_human, format_status_human, format_sync_human};
18pub use recall::{format_recall_human, format_recall_prompt_xml};
19pub use search::format_search_human;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum OutputMode {
24 Human,
26 JsonPretty,
28 Agent,
30}
31
32#[derive(Debug, Clone, Copy)]
34pub struct RenderOptions {
35 pub width: u16,
37 pub colors: bool,
39 pub compact: bool,
41}
42
43impl RenderOptions {
44 #[must_use]
46 pub fn for_terminal() -> Self {
47 use terminal_size::{Width, terminal_size};
48 let width = terminal_size().map_or(80, |(Width(w), _)| w);
49 Self {
50 width,
51 colors: crate::platform::stdout_is_tty() && crate::platform::user_accepts_ansi_color(),
52 compact: false,
53 }
54 }
55}
56
57#[must_use]
59pub fn write_stdout_bytes(bytes: &[u8]) -> u8 {
60 match io::stdout().lock().write_all(bytes) {
61 Ok(()) => exit_codes::SUCCESS,
62 Err(error) => {
63 eprintln!("Error: {error}");
64 exit_codes::GENERIC_ERROR
65 }
66 }
67}
68
69pub fn emit_response(envelope: &TalonEnvelope, mode: OutputMode) -> Result<()> {
75 match mode {
76 OutputMode::Human => human::emit(envelope),
77 OutputMode::JsonPretty => json::emit_pretty(envelope),
78 OutputMode::Agent => json::emit_agent(envelope),
79 }
80}