@@ -19,6 +19,9 @@ use vortex::error::VortexExpect;
1919use vortex:: error:: VortexResult ;
2020use vortex:: layout:: layouts:: flat:: FlatVTable ;
2121
22+ use crate :: browse:: ui:: QueryFocus ;
23+ use crate :: browse:: ui:: SortDirection ;
24+
2225mod app;
2326mod ui;
2427
@@ -47,10 +50,61 @@ enum HandleResult {
4750 Exit ,
4851}
4952
53+ #[ allow( clippy:: cognitive_complexity) ]
5054fn handle_normal_mode ( app : & mut AppState , event : Event ) -> HandleResult {
5155 if let Event :: Key ( key) = event
5256 && key. kind == KeyEventKind :: Press
5357 {
58+ // Check if we're in Query tab with SQL input focus - handle text input first
59+ let in_sql_input =
60+ app. current_tab == Tab :: Query && app. query_state . focus == QueryFocus :: SqlInput ;
61+
62+ // Handle SQL input mode - most keys should type into the input
63+ if in_sql_input {
64+ match ( key. code , key. modifiers ) {
65+ // These keys exit/switch even in SQL input mode
66+ ( KeyCode :: Tab , _) => {
67+ app. current_tab = Tab :: Layout ;
68+ }
69+ ( KeyCode :: Esc , _) => {
70+ app. query_state . toggle_focus ( ) ;
71+ }
72+ ( KeyCode :: Enter , _) => {
73+ // Execute the SQL query with COUNT(*) for pagination
74+ app. query_state . sort_column = None ;
75+ app. query_state . sort_direction = SortDirection :: None ;
76+ let file_path = app. file_path . clone ( ) ;
77+ app. query_state . execute_initial_query ( & file_path) ;
78+ // Switch focus to results table after executing
79+ app. query_state . focus = QueryFocus :: ResultsTable ;
80+ }
81+ // Navigation keys
82+ ( KeyCode :: Left , _) => app. query_state . move_cursor_left ( ) ,
83+ ( KeyCode :: Right , _) => app. query_state . move_cursor_right ( ) ,
84+ ( KeyCode :: Home , _) => app. query_state . move_cursor_start ( ) ,
85+ ( KeyCode :: End , _) => app. query_state . move_cursor_end ( ) ,
86+ // Control key shortcuts
87+ ( KeyCode :: Char ( 'a' ) , KeyModifiers :: CONTROL ) => app. query_state . move_cursor_start ( ) ,
88+ ( KeyCode :: Char ( 'e' ) , KeyModifiers :: CONTROL ) => app. query_state . move_cursor_end ( ) ,
89+ ( KeyCode :: Char ( 'u' ) , KeyModifiers :: CONTROL ) => app. query_state . clear_input ( ) ,
90+ ( KeyCode :: Char ( 'b' ) , KeyModifiers :: CONTROL ) => app. query_state . move_cursor_left ( ) ,
91+ ( KeyCode :: Char ( 'f' ) , KeyModifiers :: CONTROL ) => app. query_state . move_cursor_right ( ) ,
92+ ( KeyCode :: Char ( 'd' ) , KeyModifiers :: CONTROL ) => {
93+ app. query_state . delete_char_forward ( )
94+ }
95+ // Delete keys
96+ ( KeyCode :: Backspace , _) => app. query_state . delete_char ( ) ,
97+ ( KeyCode :: Delete , _) => app. query_state . delete_char_forward ( ) ,
98+ // All other characters get typed into the input
99+ ( KeyCode :: Char ( c) , KeyModifiers :: NONE | KeyModifiers :: SHIFT ) => {
100+ app. query_state . insert_char ( c) ;
101+ }
102+ _ => { }
103+ }
104+ return HandleResult :: Continue ;
105+ }
106+
107+ // Normal mode handling for all other cases
54108 match ( key. code , key. modifiers ) {
55109 ( KeyCode :: Char ( 'q' ) , _) => {
56110 // Close the process down.
@@ -60,9 +114,25 @@ fn handle_normal_mode(app: &mut AppState, event: Event) -> HandleResult {
60114 // toggle between tabs
61115 app. current_tab = match app. current_tab {
62116 Tab :: Layout => Tab :: Segments ,
63- Tab :: Segments => Tab :: Layout ,
117+ Tab :: Segments => Tab :: Query ,
118+ Tab :: Query => Tab :: Layout ,
64119 } ;
65120 }
121+
122+ // Query tab: Ctrl+h for previous page
123+ ( KeyCode :: Char ( 'h' ) , KeyModifiers :: CONTROL ) => {
124+ if app. current_tab == Tab :: Query {
125+ app. query_state . prev_page ( & app. file_path . clone ( ) ) ;
126+ }
127+ }
128+
129+ // Query tab: Ctrl+l for next page
130+ ( KeyCode :: Char ( 'l' ) , KeyModifiers :: CONTROL ) => {
131+ if app. current_tab == Tab :: Query {
132+ app. query_state . next_page ( & app. file_path . clone ( ) ) ;
133+ }
134+ }
135+
66136 ( KeyCode :: Up | KeyCode :: Char ( 'k' ) , _) | ( KeyCode :: Char ( 'p' ) , KeyModifiers :: CONTROL ) => {
67137 // We send the key-up to the list state if we're looking at
68138 // the Layouts tab.
@@ -75,6 +145,9 @@ fn handle_normal_mode(app: &mut AppState, event: Event) -> HandleResult {
75145 }
76146 }
77147 Tab :: Segments => app. segment_grid_state . scroll_up ( 10 ) ,
148+ Tab :: Query => {
149+ app. query_state . table_state . select_previous ( ) ;
150+ }
78151 }
79152 }
80153 ( KeyCode :: Down | KeyCode :: Char ( 'j' ) , _)
@@ -87,6 +160,9 @@ fn handle_normal_mode(app: &mut AppState, event: Event) -> HandleResult {
87160 }
88161 }
89162 Tab :: Segments => app. segment_grid_state . scroll_down ( 10 ) ,
163+ Tab :: Query => {
164+ app. query_state . table_state . select_next ( ) ;
165+ }
90166 } ,
91167 ( KeyCode :: PageUp , _) | ( KeyCode :: Char ( 'v' ) , KeyModifiers :: ALT ) => {
92168 match app. current_tab {
@@ -98,6 +174,9 @@ fn handle_normal_mode(app: &mut AppState, event: Event) -> HandleResult {
98174 }
99175 }
100176 Tab :: Segments => app. segment_grid_state . scroll_up ( 100 ) ,
177+ Tab :: Query => {
178+ app. query_state . prev_page ( & app. file_path . clone ( ) ) ;
179+ }
101180 }
102181 }
103182 ( KeyCode :: PageDown , _) | ( KeyCode :: Char ( 'v' ) , KeyModifiers :: CONTROL ) => {
@@ -110,25 +189,39 @@ fn handle_normal_mode(app: &mut AppState, event: Event) -> HandleResult {
110189 }
111190 }
112191 Tab :: Segments => app. segment_grid_state . scroll_down ( 100 ) ,
192+ Tab :: Query => {
193+ app. query_state . next_page ( & app. file_path . clone ( ) ) ;
194+ }
113195 }
114196 }
115197 ( KeyCode :: Home , _) | ( KeyCode :: Char ( '<' ) , KeyModifiers :: ALT ) => match app. current_tab {
116198 Tab :: Layout => app. layouts_list_state . select_first ( ) ,
117199 Tab :: Segments => app. segment_grid_state . scroll_left ( 200 ) ,
200+ Tab :: Query => {
201+ app. query_state . table_state . select_first ( ) ;
202+ }
118203 } ,
119204 ( KeyCode :: End , _) | ( KeyCode :: Char ( '>' ) , KeyModifiers :: ALT ) => match app. current_tab {
120205 Tab :: Layout => app. layouts_list_state . select_last ( ) ,
121206 Tab :: Segments => app. segment_grid_state . scroll_right ( 200 ) ,
207+ Tab :: Query => {
208+ app. query_state . table_state . select_last ( ) ;
209+ }
122210 } ,
123211 ( KeyCode :: Enter , _) => {
124- if app. current_tab == Tab :: Layout && app. cursor . layout ( ) . nchildren ( ) > 0 {
125- // Descend into the layout subtree for the selected child.
126- let selected = app. layouts_list_state . selected ( ) . unwrap_or_default ( ) ;
127- app. cursor = app. cursor . child ( selected) ;
212+ match app. current_tab {
213+ Tab :: Layout => {
214+ if app. cursor . layout ( ) . nchildren ( ) > 0 {
215+ // Descend into the layout subtree for the selected child.
216+ let selected = app. layouts_list_state . selected ( ) . unwrap_or_default ( ) ;
217+ app. cursor = app. cursor . child ( selected) ;
128218
129- // Reset the list scroll state and tree scroll offset.
130- app. layouts_list_state = ListState :: default ( ) . with_selected ( Some ( 0 ) ) ;
131- app. tree_scroll_offset = 0 ;
219+ // Reset the list scroll state and tree scroll offset.
220+ app. layouts_list_state = ListState :: default ( ) . with_selected ( Some ( 0 ) ) ;
221+ app. tree_scroll_offset = 0 ;
222+ }
223+ }
224+ Tab :: Query | Tab :: Segments => { }
132225 }
133226 }
134227 ( KeyCode :: Left | KeyCode :: Char ( 'h' ) , _)
@@ -142,17 +235,44 @@ fn handle_normal_mode(app: &mut AppState, event: Event) -> HandleResult {
142235 app. tree_scroll_offset = 0 ;
143236 }
144237 Tab :: Segments => app. segment_grid_state . scroll_left ( 20 ) ,
238+ Tab :: Query => {
239+ app. query_state . horizontal_scroll =
240+ app. query_state . horizontal_scroll . saturating_sub ( 1 ) ;
241+ }
145242 }
146243 }
147244 ( KeyCode :: Right | KeyCode :: Char ( 'l' ) , _) | ( KeyCode :: Char ( 'b' ) , KeyModifiers :: ALT ) => {
148245 match app. current_tab {
149246 Tab :: Layout => { }
150247 Tab :: Segments => app. segment_grid_state . scroll_right ( 20 ) ,
248+ Tab :: Query => {
249+ let max_col = app. query_state . column_count ( ) . saturating_sub ( 1 ) ;
250+ if app. query_state . horizontal_scroll < max_col {
251+ app. query_state . horizontal_scroll += 1 ;
252+ }
253+ }
151254 }
152255 }
153256
154257 ( KeyCode :: Char ( '/' ) , _) | ( KeyCode :: Char ( 's' ) , KeyModifiers :: CONTROL ) => {
155- app. key_mode = KeyMode :: Search ;
258+ if app. current_tab != Tab :: Query {
259+ app. key_mode = KeyMode :: Search ;
260+ }
261+ }
262+
263+ ( KeyCode :: Char ( 's' ) , KeyModifiers :: NONE ) => {
264+ if app. current_tab == Tab :: Query {
265+ // Sort by selected column - modifies the SQL query
266+ let col = app. query_state . selected_column ( ) ;
267+ app. query_state . apply_sort ( col, & app. file_path ) ;
268+ }
269+ }
270+
271+ ( KeyCode :: Esc , _) => {
272+ if app. current_tab == Tab :: Query {
273+ // Toggle focus in Query tab
274+ app. query_state . toggle_focus ( ) ;
275+ }
156276 }
157277
158278 // Most events not handled
0 commit comments