Skip to main content

vtcode_tui/core_tui/session/
impl_logs.rs

1use super::*;
2
3impl Session {
4    pub fn set_log_receiver(&mut self, receiver: UnboundedReceiver<LogEntry>) {
5        self.log_receiver = Some(receiver);
6    }
7
8    fn push_log_line(&mut self, text: Arc<Text<'static>>) {
9        if self.log_lines.len() >= MAX_LOG_LINES {
10            self.log_lines.pop_front();
11            self.log_evicted = true;
12        }
13        self.log_lines.push_back(text);
14        self.log_cached_text = None;
15    }
16
17    pub(crate) fn poll_log_entries(&mut self) {
18        if !self.show_logs {
19            // Drain without processing to avoid accumulation
20            if let Some(receiver) = self.log_receiver.as_mut() {
21                while receiver.try_recv().is_ok() {}
22            }
23            return;
24        }
25
26        if let Some(receiver) = self.log_receiver.as_mut() {
27            let mut drained = Vec::new();
28            while drained.len() < MAX_LOG_DRAIN_PER_TICK {
29                let Ok(entry) = receiver.try_recv() else {
30                    break;
31                };
32                drained.push(entry);
33            }
34            if !drained.is_empty() {
35                for entry in drained {
36                    let rendered = Arc::new(highlight_log_entry(&entry));
37                    self.push_log_line(rendered);
38                }
39                self.mark_dirty();
40            }
41        }
42    }
43
44    pub(crate) fn has_logs(&self) -> bool {
45        !self.log_lines.is_empty()
46    }
47
48    pub(crate) fn log_text(&mut self) -> Arc<Text<'static>> {
49        if let Some(cached) = &self.log_cached_text {
50            return Arc::clone(cached);
51        }
52
53        let mut text = Text::default();
54        if self.log_evicted {
55            text.lines.push(Line::from("(oldest logs dropped)"));
56        }
57
58        for entry in self.log_lines.iter() {
59            text.lines.extend(entry.lines.clone());
60        }
61
62        if text.lines.is_empty() {
63            text.lines.push(Line::from("No logs yet"));
64        }
65
66        let arc = Arc::new(text);
67        self.log_cached_text = Some(Arc::clone(&arc));
68        arc
69    }
70}