sql_cli/debug/
debug_trace.rs

1use std::fmt;
2
3/// A section of debug information with a title and content
4#[derive(Debug, Clone)]
5pub struct DebugSection {
6    /// The title of this debug section (e.g., "VIEWPORT STATE", "DATAVIEW STATE")
7    pub title: String,
8    /// The content of this debug section
9    pub content: String,
10    /// Priority for ordering (lower values appear first)
11    pub priority: u32,
12}
13
14impl DebugSection {
15    /// Create a new debug section
16    pub fn new(title: impl Into<String>, content: impl Into<String>, priority: u32) -> Self {
17        Self {
18            title: title.into(),
19            content: content.into(),
20            priority,
21        }
22    }
23
24    /// Create a section with a formatted title
25    pub fn with_header(
26        title: impl Into<String>,
27        content: impl Into<String>,
28        priority: u32,
29    ) -> Self {
30        let title_str = title.into();
31        let header = format!("\n========== {} ==========\n", title_str);
32        Self {
33            title: title_str,
34            content: format!("{}{}", header, content.into()),
35            priority,
36        }
37    }
38}
39
40impl fmt::Display for DebugSection {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        write!(f, "{}", self.content)
43    }
44}
45
46/// Trait for components that can provide debug information
47pub trait DebugTrace: Send + Sync {
48    /// Get the name of this debug provider
49    fn name(&self) -> &str;
50
51    /// Generate debug sections for the current state
52    /// Returns a vector of debug sections that can be displayed
53    fn debug_sections(&self) -> Vec<DebugSection>;
54
55    /// Optional method to get a quick summary (one-liner)
56    fn debug_summary(&self) -> Option<String> {
57        None
58    }
59
60    /// Check if this provider is currently active/relevant
61    fn is_active(&self) -> bool {
62        true
63    }
64}
65
66/// Priority constants for standard sections
67pub mod Priority {
68    pub const PARSER: u32 = 100;
69    pub const BUFFER: u32 = 200;
70    pub const RESULTS: u32 = 300;
71    pub const DATATABLE: u32 = 400;
72    pub const DATAVIEW: u32 = 500;
73    pub const VIEWPORT: u32 = 600;
74    pub const MEMORY: u32 = 700;
75    pub const NAVIGATION: u32 = 800;
76    pub const RENDER: u32 = 900;
77    pub const TRACE: u32 = 1000;
78    pub const STATE_LOGS: u32 = 1100;
79}
80
81/// Helper builder for creating debug sections
82pub struct DebugSectionBuilder {
83    sections: Vec<DebugSection>,
84}
85
86impl DebugSectionBuilder {
87    pub fn new() -> Self {
88        Self {
89            sections: Vec::new(),
90        }
91    }
92
93    pub fn add_section(
94        &mut self,
95        title: impl Into<String>,
96        content: impl Into<String>,
97        priority: u32,
98    ) -> &mut Self {
99        self.sections
100            .push(DebugSection::with_header(title, content, priority));
101        self
102    }
103
104    pub fn add_raw(&mut self, section: DebugSection) -> &mut Self {
105        self.sections.push(section);
106        self
107    }
108
109    pub fn add_field(&mut self, name: &str, value: impl fmt::Display) -> &mut Self {
110        if let Some(last) = self.sections.last_mut() {
111            last.content.push_str(&format!("{}: {}\n", name, value));
112        }
113        self
114    }
115
116    pub fn add_line(&mut self, line: impl Into<String>) -> &mut Self {
117        if let Some(last) = self.sections.last_mut() {
118            last.content.push_str(&format!("{}\n", line.into()));
119        }
120        self
121    }
122
123    pub fn build(self) -> Vec<DebugSection> {
124        self.sections
125    }
126}
127
128impl Default for DebugSectionBuilder {
129    fn default() -> Self {
130        Self::new()
131    }
132}