chabeau 0.7.3

A full-screen terminal chat interface that connects to various AI APIs for real-time conversations
Documentation
use crate::core::app::ui_state::UiFocus;
use crate::core::app::App;
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;

const SEPARATOR: &str = "";

#[derive(Debug, Clone)]
struct FieldVariant {
    text: String,
    width: usize,
}

impl FieldVariant {
    fn new(text: String) -> Self {
        let width = UnicodeWidthStr::width(text.as_str());
        Self { text, width }
    }
}

fn build_variants(label: &str, value: &str) -> Vec<FieldVariant> {
    let mut variants = Vec::new();
    let full_text = format!("{}{}", label, value);
    variants.push(FieldVariant::new(full_text));

    let graphemes: Vec<&str> = UnicodeSegmentation::graphemes(value, true).collect();
    if graphemes.len() > 3 {
        for keep in (3..graphemes.len()).rev() {
            let mut truncated_value = graphemes[..keep].concat();
            truncated_value.push('');
            let text = format!("{}{}", label, truncated_value);
            if variants
                .last()
                .map(|variant| variant.text == text)
                .unwrap_or(false)
            {
                continue;
            }
            variants.push(FieldVariant::new(text));
        }
    }

    variants
}

fn compute_total_width(
    base_width: usize,
    logging_width: usize,
    char_variant: Option<&FieldVariant>,
    preset_variant: Option<&FieldVariant>,
    mcp_variant: Option<&FieldVariant>,
    separator_width: usize,
) -> usize {
    let mut widths = vec![base_width];
    if let Some(char_variant) = char_variant {
        widths.push(char_variant.width);
    }
    if let Some(preset_variant) = preset_variant {
        widths.push(preset_variant.width);
    }
    if let Some(mcp_variant) = mcp_variant {
        widths.push(mcp_variant.width);
    }
    widths.push(logging_width);

    let separators = widths.len().saturating_sub(1);
    widths.into_iter().sum::<usize>() + separators * separator_width
}

fn select_char_only(
    char_variants: &[FieldVariant],
    base_width: usize,
    logging_width: usize,
    separator_width: usize,
    available_width: usize,
) -> Option<usize> {
    for (index, variant) in char_variants.iter().enumerate() {
        if compute_total_width(
            base_width,
            logging_width,
            Some(variant),
            None,
            None,
            separator_width,
        ) <= available_width
        {
            return Some(index);
        }
    }

    None
}

fn select_preset_only(
    preset_variants: &[FieldVariant],
    base_width: usize,
    logging_width: usize,
    separator_width: usize,
    available_width: usize,
) -> Option<usize> {
    for (index, variant) in preset_variants.iter().enumerate() {
        if compute_total_width(
            base_width,
            logging_width,
            None,
            Some(variant),
            None,
            separator_width,
        ) <= available_width
        {
            return Some(index);
        }
    }

    None
}

fn select_char_and_preset(
    char_variants: &[FieldVariant],
    preset_variants: &[FieldVariant],
    base_width: usize,
    logging_width: usize,
    separator_width: usize,
    available_width: usize,
) -> Option<(usize, usize)> {
    if char_variants.is_empty() || preset_variants.is_empty() {
        return None;
    }

    let preset_full = &preset_variants[0];
    for (index, char_variant) in char_variants.iter().enumerate() {
        if compute_total_width(
            base_width,
            logging_width,
            Some(char_variant),
            Some(preset_full),
            None,
            separator_width,
        ) <= available_width
        {
            return Some((index, 0));
        }
    }

    for (preset_index, preset_variant) in preset_variants.iter().enumerate().skip(1) {
        for (char_index, char_variant) in char_variants.iter().enumerate() {
            if compute_total_width(
                base_width,
                logging_width,
                Some(char_variant),
                Some(preset_variant),
                None,
                separator_width,
            ) <= available_width
            {
                return Some((char_index, preset_index));
            }
        }
    }

    None
}

fn assemble_title(
    base: &str,
    char_variant: Option<&FieldVariant>,
    preset_variant: Option<&FieldVariant>,
    mcp_variant: Option<&FieldVariant>,
    logging: &FieldVariant,
) -> String {
    let mut parts: Vec<&str> = Vec::new();
    parts.push(base);
    if let Some(char_variant) = char_variant {
        parts.push(char_variant.text.as_str());
    }
    if let Some(preset_variant) = preset_variant {
        parts.push(preset_variant.text.as_str());
    }
    if let Some(mcp_variant) = mcp_variant {
        parts.push(mcp_variant.text.as_str());
    }
    parts.push(logging.text.as_str());
    parts.join(SEPARATOR)
}

fn mcp_field(app: &App) -> Option<FieldVariant> {
    let enabled_servers: Vec<_> = app
        .mcp
        .servers()
        .filter(|server| server.config.is_enabled())
        .collect();

    if enabled_servers.is_empty() {
        return None;
    }

    let status = if app.session.mcp_tools_unsupported {
        "unsupported"
    } else if app.session.mcp_init.in_progress {
        "loading"
    } else if enabled_servers
        .iter()
        .any(|server| server.last_error.is_some())
    {
        "error"
    } else if enabled_servers.iter().any(|server| server.connected) {
        "connected"
    } else if app.session.mcp_init.complete {
        "error"
    } else {
        "loading"
    };

    Some(FieldVariant::new(format!("MCP: {}", status)))
}

pub fn build_main_title(app: &App, available_width: u16) -> String {
    let available_width = available_width as usize;

    let model_display = if app.picker.in_provider_model_transition || app.session.model.is_empty() {
        "no model selected".to_string()
    } else {
        app.session.model.clone()
    };
    let provider_display = if app.session.provider_display_name.trim().is_empty() {
        "(no provider selected)".to_string()
    } else {
        app.session.provider_display_name.clone()
    };

    let focus_prefix = if app.ui.focus == UiFocus::Transcript {
        ""
    } else {
        "· "
    };
    let base_text = format!(
        "{}Chabeau v{} - {} ({})",
        focus_prefix,
        env!("CARGO_PKG_VERSION"),
        provider_display,
        model_display
    );
    let base_width = UnicodeWidthStr::width(base_text.as_str());

    let logging_variant = FieldVariant::new(format!("Logging: {}", app.get_logging_status()));

    let char_variants = app
        .session
        .active_character
        .as_ref()
        .map(|character| build_variants("Character: ", character.data.name.as_str()));
    let preset_variants = app
        .preset_manager
        .get_active_preset()
        .map(|preset| build_variants("Preset: ", preset.id.as_str()));
    let mcp_variant = mcp_field(app);

    let separator_width = UnicodeWidthStr::width(SEPARATOR);

    let mut selected_char: Option<&FieldVariant> = None;
    let mut selected_preset: Option<&FieldVariant> = None;

    if let Some(char_variants) = char_variants.as_ref() {
        if let Some(preset_variants) = preset_variants.as_ref() {
            if let Some((char_index, preset_index)) = select_char_and_preset(
                char_variants,
                preset_variants,
                base_width,
                logging_variant.width,
                separator_width,
                available_width,
            ) {
                selected_char = Some(&char_variants[char_index]);
                selected_preset = Some(&preset_variants[preset_index]);
            }
        } else if let Some(char_index) = select_char_only(
            char_variants,
            base_width,
            logging_variant.width,
            separator_width,
            available_width,
        ) {
            selected_char = Some(&char_variants[char_index]);
        }
    }

    if selected_preset.is_none() {
        if let Some(preset_variants) = preset_variants.as_ref() {
            if let Some(preset_index) = select_preset_only(
                preset_variants,
                base_width,
                logging_variant.width,
                separator_width,
                available_width,
            ) {
                selected_preset = Some(&preset_variants[preset_index]);
            }
        }
    }

    if let Some(mcp_variant) = mcp_variant.as_ref() {
        if compute_total_width(
            base_width,
            logging_variant.width,
            selected_char,
            selected_preset,
            Some(mcp_variant),
            separator_width,
        ) <= available_width
        {
            return assemble_title(
                &base_text,
                selected_char,
                selected_preset,
                Some(mcp_variant),
                &logging_variant,
            );
        }
    }

    assemble_title(
        &base_text,
        selected_char,
        selected_preset,
        None,
        &logging_variant,
    )
}