sql_cli/debug/
buffer_debug.rs1use crate::buffer::BufferAPI;
2use crate::debug::debug_trace::{DebugSection, DebugSectionBuilder, DebugTrace, Priority};
3use std::sync::Arc;
4
5pub 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) -> &'static str {
18 "Buffer"
19 }
20
21 fn debug_sections(&self) -> Vec<DebugSection> {
22 let mut builder = DebugSectionBuilder::new();
23
24 builder.add_section("BUFFER STATE", "", Priority::BUFFER);
26
27 builder.add_field("Buffer Name", self.buffer.get_name());
29 builder.add_field("Current Mode", format!("{:?}", self.buffer.get_mode()));
30
31 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 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 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 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 let (scroll_row, scroll_col) = self.buffer.get_scroll_offset();
78 builder.add_field(
79 "Scroll Offset",
80 format!("row={scroll_row}, col={scroll_col}"),
81 );
82
83 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 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 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
131pub struct BufferManagerDebugProvider {
133 buffers: Vec<Arc<dyn BufferAPI>>,
134 current_index: usize,
135}
136
137impl BufferManagerDebugProvider {
138 #[must_use]
139 pub fn new(buffers: Vec<Arc<dyn BufferAPI>>, current_index: usize) -> Self {
140 Self {
141 buffers,
142 current_index,
143 }
144 }
145}
146
147impl DebugTrace for BufferManagerDebugProvider {
148 fn name(&self) -> &'static str {
149 "BufferManager"
150 }
151
152 fn debug_sections(&self) -> Vec<DebugSection> {
153 let mut builder = DebugSectionBuilder::new();
154
155 builder.add_section("BUFFER MANAGER", "", Priority::BUFFER - 10);
156
157 builder.add_field("Total Buffers", self.buffers.len());
158 builder.add_field("Current Buffer Index", self.current_index);
159
160 if let Some(current) = self.buffers.get(self.current_index) {
161 builder.add_field("Current Buffer Name", current.get_name());
162 }
163
164 builder.add_line("");
165 builder.add_line("All Buffers:");
166 for (idx, buffer) in self.buffers.iter().enumerate() {
167 let marker = if idx == self.current_index {
168 " * "
169 } else {
170 " "
171 };
172 let mode = buffer.get_mode();
173 let has_data = buffer.get_dataview().is_some();
174 builder.add_line(format!(
175 "{} [{}] {} - Mode: {:?}, Data: {}",
176 marker,
177 idx,
178 buffer.get_name(),
179 mode,
180 if has_data { "Yes" } else { "No" }
181 ));
182 }
183
184 builder.build()
185 }
186
187 fn debug_summary(&self) -> Option<String> {
188 Some(format!(
189 "{} buffers, current: #{} ({})",
190 self.buffers.len(),
191 self.current_index,
192 self.buffers
193 .get(self.current_index)
194 .map_or_else(|| "none".to_string(), |b| b.get_name())
195 ))
196 }
197}