tenere 0.11.0

TUI interface for LLMs written in Rust
Documentation
use crate::history::History;
use crate::prompt::Prompt;
use crate::{chat::Chat, help::Help};
use std;
use std::sync::atomic::AtomicBool;

use crate::notification::Notification;
use crate::spinner::Spinner;
use crate::{config::Config, formatter::Formatter};
use arboard::Clipboard;
use crossterm::event::KeyCode;
use ratatui::text::Line;

use std::sync::Arc;

pub type AppResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;

#[derive(Debug, Clone, PartialEq)]
pub enum FocusedBlock {
    Prompt,
    Chat,
    History,
    Preview,
    Help,
}

pub struct App<'a> {
    pub running: bool,
    pub prompt: Prompt<'a>,
    pub chat: Chat<'a>,
    pub focused_block: FocusedBlock,
    pub history: History<'a>,
    pub notifications: Vec<Notification>,
    pub spinner: Spinner,
    pub terminate_response_signal: Arc<AtomicBool>,
    pub clipboard: Option<Clipboard>,
    pub help: Help,
    pub previous_key: KeyCode,
    pub config: Arc<Config>,
    pub formatter: &'a Formatter<'a>,
}

impl<'a> App<'a> {
    pub fn new(config: Arc<Config>, formatter: &'a Formatter<'a>) -> Self {
        Self {
            running: true,
            prompt: Prompt::default(),
            chat: Chat::new(),
            focused_block: FocusedBlock::Prompt,
            history: History::new(),
            notifications: Vec::new(),
            spinner: Spinner::default(),
            terminate_response_signal: Arc::new(AtomicBool::new(false)),
            clipboard: Clipboard::new().ok(),
            help: Help::new(),
            previous_key: KeyCode::Null,
            config,
            formatter,
        }
    }

    pub fn tick(&mut self) {
        self.notifications.retain(|n| n.ttl > 0);
        self.notifications.iter_mut().for_each(|n| n.ttl -= 1);

        if self.spinner.active {
            self.chat.formatted_chat.lines.pop();
            self.chat
                .formatted_chat
                .lines
                .push(Line::raw(format!("🤖: Waiting {}", self.spinner.draw())));
            self.spinner.update();
        }
    }
}