sql_cli/
global_state.rs

1use crate::api_client::ApiClient;
2use crate::cache::QueryCache;
3use crate::config::config::Config;
4use crate::history::CommandHistory;
5use crate::hybrid_parser::HybridParser;
6use crate::parser::SqlParser;
7use crate::sql_highlighter::SqlHighlighter;
8
9/// GlobalState contains all truly application-wide state that is shared across all buffers
10/// This includes services, parsers, configuration, and global UI state
11pub struct GlobalState {
12    // --- Core Services ---
13    pub api_client: ApiClient,
14    pub sql_parser: SqlParser,
15    pub hybrid_parser: HybridParser,
16    pub sql_highlighter: SqlHighlighter,
17    pub config: Config,
18    pub command_history: CommandHistory,
19    pub query_cache: Option<QueryCache>,
20
21    // --- Global UI State ---
22    pub show_help: bool,
23    pub help_scroll: u16,
24    pub debug_text: String,
25    pub debug_scroll: u16,
26    pub input_scroll_offset: u16, // Horizontal scroll for input
27
28    // --- Global Selection/Clipboard ---
29    pub selection_mode: SelectionMode,
30    pub yank_mode: Option<char>,
31    pub last_yanked: Option<(String, String)>, // (description, value)
32
33    // --- Completion & History ---
34    pub completion_state: CompletionState,
35    pub history_state: HistoryState,
36
37    // --- Global Dialogs ---
38    pub jump_to_row_input: String,
39
40    // --- Cache Mode ---
41    pub cache_mode: bool,
42}
43
44#[derive(Clone, PartialEq)]
45pub enum SelectionMode {
46    Row,
47    Cell,
48}
49
50#[derive(Clone)]
51pub struct CompletionState {
52    pub suggestions: Vec<String>,
53    pub current_index: usize,
54    pub last_query: String,
55    pub last_cursor_pos: usize,
56}
57
58#[derive(Clone)]
59pub struct HistoryState {
60    pub search_query: String,
61    pub matches: Vec<(usize, String)>, // (index, command)
62    pub selected_index: usize,
63}
64
65impl GlobalState {
66    pub fn new(api_url: &str, config: Config) -> Self {
67        Self {
68            api_client: ApiClient::new(api_url),
69            sql_parser: SqlParser::new(),
70            hybrid_parser: HybridParser::new(),
71            sql_highlighter: SqlHighlighter::new(),
72            command_history: CommandHistory::new().unwrap_or_default(),
73            query_cache: None,
74            config,
75
76            show_help: false,
77            help_scroll: 0,
78            debug_text: String::new(),
79            debug_scroll: 0,
80            input_scroll_offset: 0,
81
82            selection_mode: SelectionMode::Row,
83            yank_mode: None,
84            last_yanked: None,
85
86            completion_state: CompletionState {
87                suggestions: Vec::new(),
88                current_index: 0,
89                last_query: String::new(),
90                last_cursor_pos: 0,
91            },
92
93            history_state: HistoryState {
94                search_query: String::new(),
95                matches: Vec::new(),
96                selected_index: 0,
97            },
98
99            jump_to_row_input: String::new(),
100
101            cache_mode: false,
102        }
103    }
104
105    /// Toggle help display
106    pub fn toggle_help(&mut self) {
107        self.show_help = !self.show_help;
108        if self.show_help {
109            self.help_scroll = 0; // Reset scroll when opening help
110        }
111    }
112
113    /// Clear debug text
114    pub fn clear_debug(&mut self) {
115        self.debug_text.clear();
116        self.debug_scroll = 0;
117    }
118
119    /// Add line to debug text
120    pub fn add_debug_line(&mut self, line: String) {
121        if !self.debug_text.is_empty() {
122            self.debug_text.push('\n');
123        }
124        self.debug_text.push_str(&line);
125    }
126
127    /// Toggle selection mode between Row and Cell
128    pub fn toggle_selection_mode(&mut self) {
129        self.selection_mode = match self.selection_mode {
130            SelectionMode::Row => SelectionMode::Cell,
131            SelectionMode::Cell => SelectionMode::Row,
132        };
133    }
134
135    /// Check if in cell selection mode
136    pub fn is_cell_mode(&self) -> bool {
137        matches!(self.selection_mode, SelectionMode::Cell)
138    }
139
140    /// Toggle cache mode
141    pub fn toggle_cache_mode(&mut self) {
142        self.cache_mode = !self.cache_mode;
143    }
144
145    /// Initialize query cache if not already present
146    pub fn init_cache(&mut self, _cache_dir: Option<std::path::PathBuf>) {
147        if self.query_cache.is_none() {
148            self.query_cache = QueryCache::new().ok();
149        }
150    }
151}