vtcode_tui/core_tui/session/
impl_logs.rs1use 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 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}