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    #[must_use]
67    pub fn new(api_url: &str, config: Config) -> Self {
68        Self {
69            api_client: ApiClient::new(api_url),
70            sql_parser: SqlParser::new(),
71            hybrid_parser: HybridParser::new(),
72            sql_highlighter: SqlHighlighter::new(),
73            command_history: CommandHistory::new().unwrap_or_default(),
74            query_cache: None,
75            config,
76
77            show_help: false,
78            help_scroll: 0,
79            debug_text: String::new(),
80            debug_scroll: 0,
81            input_scroll_offset: 0,
82
83            selection_mode: SelectionMode::Row,
84            yank_mode: None,
85            last_yanked: None,
86
87            completion_state: CompletionState {
88                suggestions: Vec::new(),
89                current_index: 0,
90                last_query: String::new(),
91                last_cursor_pos: 0,
92            },
93
94            history_state: HistoryState {
95                search_query: String::new(),
96                matches: Vec::new(),
97                selected_index: 0,
98            },
99
100            jump_to_row_input: String::new(),
101
102            cache_mode: false,
103        }
104    }
105
106    /// Toggle help display
107    pub fn toggle_help(&mut self) {
108        self.show_help = !self.show_help;
109        if self.show_help {
110            self.help_scroll = 0; // Reset scroll when opening help
111        }
112    }
113
114    /// Clear debug text
115    pub fn clear_debug(&mut self) {
116        self.debug_text.clear();
117        self.debug_scroll = 0;
118    }
119
120    /// Add line to debug text
121    pub fn add_debug_line(&mut self, line: String) {
122        if !self.debug_text.is_empty() {
123            self.debug_text.push('\n');
124        }
125        self.debug_text.push_str(&line);
126    }
127
128    /// Toggle selection mode between Row and Cell
129    pub fn toggle_selection_mode(&mut self) {
130        self.selection_mode = match self.selection_mode {
131            SelectionMode::Row => SelectionMode::Cell,
132            SelectionMode::Cell => SelectionMode::Row,
133        };
134    }
135
136    /// Check if in cell selection mode
137    pub fn is_cell_mode(&self) -> bool {
138        matches!(self.selection_mode, SelectionMode::Cell)
139    }
140
141    /// Toggle cache mode
142    pub fn toggle_cache_mode(&mut self) {
143        self.cache_mode = !self.cache_mode;
144    }
145
146    /// Initialize query cache if not already present
147    pub fn init_cache(&mut self, _cache_dir: Option<std::path::PathBuf>) {
148        if self.query_cache.is_none() {
149            self.query_cache = QueryCache::new().ok();
150        }
151    }
152}