sql_cli/debug/
buffer_debug.rs

1use crate::buffer::BufferAPI;
2use crate::debug::debug_trace::{DebugSection, DebugSectionBuilder, DebugTrace, Priority};
3use std::sync::Arc;
4
5/// Debug trace implementation for Buffer
6pub struct BufferDebugProvider {
7    buffer: Arc<dyn BufferAPI>,
8}
9
10impl BufferDebugProvider {
11    pub fn new(buffer: Arc<dyn BufferAPI>) -> Self {
12        Self { buffer }
13    }
14}
15
16impl DebugTrace for BufferDebugProvider {
17    fn name(&self) -> &str {
18        "Buffer"
19    }
20
21    fn debug_sections(&self) -> Vec<DebugSection> {
22        let mut builder = DebugSectionBuilder::new();
23
24        // Main buffer state section
25        builder.add_section("BUFFER STATE", "", Priority::BUFFER);
26
27        // Basic buffer info
28        builder.add_field("Buffer Name", self.buffer.get_name());
29        builder.add_field("Current Mode", format!("{:?}", self.buffer.get_mode()));
30
31        // Input state
32        let input_text = self.buffer.get_input_text();
33        builder.add_field(
34            "Input Text",
35            if input_text.is_empty() {
36                "(empty)".to_string()
37            } else {
38                format!("'{}' ({} chars)", input_text, input_text.len())
39            },
40        );
41
42        // Navigation state
43        if let Some(selected_row) = self.buffer.get_selected_row() {
44            builder.add_field("Selected Row", selected_row);
45        } else {
46            builder.add_field("Selected Row", "None");
47        }
48        builder.add_field("Current Column", self.buffer.get_current_column());
49
50        // Query information
51        let last_query = self.buffer.get_last_query();
52        if !last_query.is_empty() {
53            builder.add_field(
54                "Last Query",
55                format!(
56                    "'{}' ({} chars)",
57                    if last_query.len() > 50 {
58                        format!("{}...", &last_query[..50])
59                    } else {
60                        last_query.clone()
61                    },
62                    last_query.len()
63                ),
64            );
65        }
66
67        // Results information
68        if let Some(dataview) = self.buffer.get_dataview() {
69            builder.add_field("Has DataView", "Yes");
70            builder.add_field("Result Rows", dataview.row_count());
71            builder.add_field("Result Columns", dataview.column_count());
72        } else {
73            builder.add_field("Has DataView", "No");
74        }
75
76        // Scroll state
77        let (scroll_row, scroll_col) = self.buffer.get_scroll_offset();
78        builder.add_field(
79            "Scroll Offset",
80            format!("row={}, col={}", scroll_row, scroll_col),
81        );
82
83        // Viewport lock state
84        builder.add_field(
85            "Viewport Lock",
86            if self.buffer.is_viewport_lock() {
87                if let Some(lock_row) = self.buffer.get_viewport_lock_row() {
88                    format!("Locked at row {}", lock_row)
89                } else {
90                    "Locked (no specific row)".to_string()
91                }
92            } else {
93                "Unlocked".to_string()
94            },
95        );
96
97        // Filter state
98        let filter_pattern = self.buffer.get_filter_pattern();
99        if !filter_pattern.is_empty() {
100            builder.add_field("Filter Pattern", format!("'{}'", filter_pattern));
101            builder.add_field("Filter Active", self.buffer.is_filter_active());
102        }
103
104        // Status message
105        let status_msg = self.buffer.get_status_message();
106        if !status_msg.is_empty() {
107            builder.add_field("Status Message", status_msg);
108        }
109
110        builder.build()
111    }
112
113    fn debug_summary(&self) -> Option<String> {
114        let mode = self.buffer.get_mode();
115        let has_data = self.buffer.get_dataview().is_some();
116        let input_len = self.buffer.get_input_text().len();
117
118        Some(format!(
119            "Mode: {:?}, Input: {} chars, Data: {}",
120            mode,
121            input_len,
122            if has_data { "Yes" } else { "No" }
123        ))
124    }
125
126    fn is_active(&self) -> bool {
127        true
128    }
129}
130
131/// Debug provider for multiple buffers (BufferManager)
132pub struct BufferManagerDebugProvider {
133    buffers: Vec<Arc<dyn BufferAPI>>,
134    current_index: usize,
135}
136
137impl BufferManagerDebugProvider {
138    pub fn new(buffers: Vec<Arc<dyn BufferAPI>>, current_index: usize) -> Self {
139        Self {
140            buffers,
141            current_index,
142        }
143    }
144}
145
146impl DebugTrace for BufferManagerDebugProvider {
147    fn name(&self) -> &str {
148        "BufferManager"
149    }
150
151    fn debug_sections(&self) -> Vec<DebugSection> {
152        let mut builder = DebugSectionBuilder::new();
153
154        builder.add_section("BUFFER MANAGER", "", Priority::BUFFER - 10);
155
156        builder.add_field("Total Buffers", self.buffers.len());
157        builder.add_field("Current Buffer Index", self.current_index);
158
159        if let Some(current) = self.buffers.get(self.current_index) {
160            builder.add_field("Current Buffer Name", current.get_name());
161        }
162
163        builder.add_line("");
164        builder.add_line("All Buffers:");
165        for (idx, buffer) in self.buffers.iter().enumerate() {
166            let marker = if idx == self.current_index {
167                " * "
168            } else {
169                "   "
170            };
171            let mode = buffer.get_mode();
172            let has_data = buffer.get_dataview().is_some();
173            builder.add_line(format!(
174                "{} [{}] {} - Mode: {:?}, Data: {}",
175                marker,
176                idx,
177                buffer.get_name(),
178                mode,
179                if has_data { "Yes" } else { "No" }
180            ));
181        }
182
183        builder.build()
184    }
185
186    fn debug_summary(&self) -> Option<String> {
187        Some(format!(
188            "{} buffers, current: #{} ({})",
189            self.buffers.len(),
190            self.current_index,
191            self.buffers
192                .get(self.current_index)
193                .map(|b| b.get_name())
194                .unwrap_or_else(|| "none".to_string())
195        ))
196    }
197}