crashdump_parser/
handler.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::app::{App, AppResult, ProcessViewState, SelectedTab};
16use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
17
18/// Handles the key events and updates the state of [`App`].
19pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
20    match app.selected_tab {
21        SelectedTab::Inspect => {
22            match key_event.code {
23                // Exit application on `ESC` or `q`
24                KeyCode::Esc | KeyCode::Char('q') => {
25                    app.quit();
26                }
27                // Exit application on `Ctrl-C`
28                KeyCode::Char('c') | KeyCode::Char('C') => {
29                    if key_event.modifiers == KeyModifiers::CONTROL {
30                        app.quit();
31                    }
32                }
33
34                KeyCode::Char('i') | KeyCode::Char('I') => {
35                    app.selected_tab = SelectedTab::Process;
36                }
37
38                KeyCode::Right => app.next_tab(),
39                KeyCode::Left => app.prev_tab(),
40        
41                KeyCode::Char('j') | KeyCode::Down => app.inspect_scroll_state.scroll_down(),
42                KeyCode::Char('k') | KeyCode::Up => app.inspect_scroll_state.scroll_up(),
43                KeyCode::Char('f') | KeyCode::PageDown => app.inspect_scroll_state.scroll_page_down(),
44                KeyCode::Char('b') | KeyCode::PageUp => app.inspect_scroll_state.scroll_page_up(),
45                KeyCode::Char('g') | KeyCode::Home => app.inspect_scroll_state.scroll_to_top(),
46                KeyCode::Char('G') | KeyCode::End => app.inspect_scroll_state.scroll_to_bottom(),
47
48                _ => {}
49            }
50        }
51        _ => {
52            match key_event.code {
53                // Exit application on `ESC` or `q`
54                KeyCode::Esc | KeyCode::Char('q') => {
55                    app.quit();
56                }
57                // Exit application on `Ctrl-C`
58                KeyCode::Char('c') | KeyCode::Char('C') => {
59                    if key_event.modifiers == KeyModifiers::CONTROL {
60                        app.quit();
61                    }
62                }
63                // Tab switching
64                KeyCode::Right => app.next_tab(),
65                KeyCode::Left => app.prev_tab(),
66        
67                KeyCode::Down => {
68                    if let Some(table_state) = app.table_states.get_mut(&app.selected_tab) {
69                        if let Some(selected) = table_state.selected() {
70                            let amount_items = app.tab_lists[&app.selected_tab].len();
71                            if selected >= amount_items - 1 {
72                                table_state.select(Some(0));
73                            } else {
74                                table_state.select(Some(selected + 1));
75                            }
76                        }
77                    }
78                }
79        
80                KeyCode::Char('s') | KeyCode::Char('S') => {
81                    if app.selected_tab == SelectedTab::Process {
82                        app.process_view_state = ProcessViewState::Stack;
83                    }
84                }
85        
86                KeyCode::Char('h') | KeyCode::Char('H') => {
87                    if app.selected_tab == SelectedTab::Process {
88                        app.process_view_state = ProcessViewState::Heap;
89                    }
90                }
91        
92                KeyCode::Char('m') | KeyCode::Char('M') => {
93                    if app.selected_tab == SelectedTab::Process {
94                        app.process_view_state = ProcessViewState::MessageQueue;
95                    }
96                }
97
98                KeyCode::Char('i') | KeyCode::Char('I') => {
99                    if app.selected_tab == SelectedTab::Process {
100                        app.selected_tab = SelectedTab::Inspect;
101                    }
102                }
103        
104                KeyCode::Up => {
105                    if let Some(table_state) = app.table_states.get_mut(&app.selected_tab) {
106                        if let Some(selected) = table_state.selected() {
107                            let amount_items = app.tab_lists[&app.selected_tab].len();
108                            if selected > 0 {
109                                table_state.select(Some(selected - 1));
110                            } else {
111                                table_state.select(Some(amount_items - 1));
112                            }
113                        }
114                    }
115                }
116                
117                _ => {}
118                
119            }
120        }
121    }
122    
123    Ok(())
124}