gdelt 0.1.0

CLI for GDELT Project - optimized for agentic usage with local data caching
//! Markdown output formatting

use crate::cli::output::Tabular;
use crate::error::Result;

/// Markdown output formatter
pub struct MarkdownOutput;

impl MarkdownOutput {
    pub fn new() -> Self {
        Self
    }

    /// Print a single value as markdown
    pub fn print<T: Tabular>(&self, value: &T) -> Result<()> {
        let headers = T::headers();
        let row = value.row();

        // Print as definition list for single items
        for (key, val) in headers.iter().zip(row.iter()) {
            println!("**{key}**: {val}  ");
        }

        Ok(())
    }

    /// Print multiple values as markdown table
    pub fn print_rows<T: Tabular>(&self, values: &[T]) -> Result<()> {
        if values.is_empty() {
            println!("*No results*");
            return Ok(());
        }

        let headers = T::headers();

        // Header row
        print!("|");
        for header in &headers {
            print!(" {header} |");
        }
        println!();

        // Separator row
        print!("|");
        for _ in &headers {
            print!(" --- |");
        }
        println!();

        // Data rows
        for value in values {
            print!("|");
            for cell in value.row() {
                // Escape pipe characters in cell content
                let escaped = cell.replace('|', "\\|");
                print!(" {escaped} |");
            }
            println!();
        }

        Ok(())
    }

    /// Print a heading
    pub fn heading(&self, level: u8, text: &str) {
        let prefix = "#".repeat(level as usize);
        println!("\n{prefix} {text}\n");
    }

    /// Print a code block
    pub fn code_block(&self, language: &str, code: &str) {
        println!("```{language}");
        println!("{code}");
        println!("```");
    }
}

impl Default for MarkdownOutput {
    fn default() -> Self {
        Self::new()
    }
}