@@ -26,13 +26,21 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
2626pub fn handle_command ( key_event : KeyEvent , app : & mut App ) -> AppResult < ( ) > {
2727 let mut key_handled = handle_command_generic ( key_event, app) ?;
2828 if !key_handled {
29- match app. flamegraph_state ( ) . view_kind {
29+ let view = app. flamegraph_state ( ) . view_kind ;
30+ let tree_mode = app. flamegraph_view . state . tree_mode ;
31+ match view {
3032 ViewKind :: FlameGraph => {
3133 key_handled = handle_command_flamegraph ( key_event, app) ?;
3234 }
35+ ViewKind :: Table | ViewKind :: ProcessList if tree_mode => {
36+ key_handled = handle_command_tree_view ( key_event, app) ?;
37+ }
3338 ViewKind :: Table => {
3439 key_handled = handle_command_table ( key_event, app) ?;
3540 }
41+ ViewKind :: ProcessList => {
42+ key_handled = handle_command_process_list ( key_event, app) ?;
43+ }
3644 ViewKind :: Output => {
3745 key_handled = handle_command_output ( key_event, app) ?;
3846 }
@@ -90,6 +98,15 @@ pub fn handle_command_generic(key_event: KeyEvent, app: &mut App) -> AppResult<b
9098 KeyCode :: Char ( '?' ) => {
9199 app. toggle_debug ( ) ;
92100 }
101+ KeyCode :: Char ( 't' ) => {
102+ app. flamegraph_view . state . tree_mode = !app. flamegraph_view . state . tree_mode ;
103+ let mode_str = if app. flamegraph_view . state . tree_mode {
104+ "on"
105+ } else {
106+ "off"
107+ } ;
108+ app. set_transient_message ( & format ! ( "Tree mode: {}" , mode_str) ) ;
109+ }
93110 _ => {
94111 key_handled = false ;
95112 }
@@ -142,6 +159,15 @@ fn handle_command_flamegraph(key_event: KeyEvent, app: &mut App) -> AppResult<bo
142159 KeyCode :: Char ( '#' ) => {
143160 app. search_selected ( ) ;
144161 }
162+ KeyCode :: Char ( 'p' ) => {
163+ let new_val = !app. flamegraph_view . state . pid_mode ;
164+ app. flamegraph_view . state . pid_mode = new_val;
165+ // Sync to shared handle so profiling thread picks it up
166+ app. get_pid_mode_handle ( )
167+ . store ( new_val, std:: sync:: atomic:: Ordering :: Relaxed ) ;
168+ let mode_str = if new_val { "on" } else { "off" } ;
169+ app. set_transient_message ( & format ! ( "PID mode: {}" , mode_str) ) ;
170+ }
145171 _ => {
146172 key_handled = false ;
147173 }
@@ -228,6 +254,114 @@ fn handle_command_output(key_event: KeyEvent, app: &mut App) -> AppResult<bool>
228254 Ok ( key_handled)
229255}
230256
257+ fn handle_command_process_list ( key_event : KeyEvent , app : & mut App ) -> AppResult < bool > {
258+ let process_count = app. flamegraph_view . get_process_list ( ) . len ( ) ;
259+ let mut key_handled = true ;
260+ match key_event. code {
261+ KeyCode :: Down | KeyCode :: Char ( 'j' ) => {
262+ if process_count > 0 {
263+ let state = & mut app. flamegraph_view . state . process_list_state ;
264+ state. selected = ( state. selected + 1 ) . min ( process_count. saturating_sub ( 1 ) ) ;
265+ }
266+ }
267+ KeyCode :: Up | KeyCode :: Char ( 'k' ) => {
268+ let state = & mut app. flamegraph_view . state . process_list_state ;
269+ state. selected = state. selected . saturating_sub ( 1 ) ;
270+ }
271+ KeyCode :: Char ( 'G' ) => {
272+ if process_count > 0 {
273+ app. flamegraph_view . state . process_list_state . selected =
274+ process_count. saturating_sub ( 1 ) ;
275+ }
276+ }
277+ KeyCode :: Char ( 'g' ) => {
278+ app. flamegraph_view . state . process_list_state . selected = 0 ;
279+ }
280+ KeyCode :: Enter => {
281+ let processes = app. flamegraph_view . get_process_list ( ) ;
282+ let selected = app. flamegraph_view . state . process_list_state . selected ;
283+ if let Some ( entry) = processes. get ( selected) {
284+ app. flamegraph_view . zoom_to_process ( entry. stack_id ) ;
285+ }
286+ }
287+ KeyCode :: Esc | KeyCode :: Char ( 'p' ) => {
288+ app. flamegraph_view . state . view_kind = ViewKind :: FlameGraph ;
289+ }
290+ _ => {
291+ key_handled = false ;
292+ }
293+ }
294+ Ok ( key_handled)
295+ }
296+
297+ fn handle_command_tree_view ( key_event : KeyEvent , app : & mut App ) -> AppResult < bool > {
298+ let rows = app. flamegraph_view . get_tree_rows ( ) ;
299+ let row_count = rows. len ( ) ;
300+ let mut key_handled = true ;
301+ match key_event. code {
302+ KeyCode :: Down | KeyCode :: Char ( 'j' ) => {
303+ if row_count > 0 {
304+ let state = & mut app. flamegraph_view . state . tree_view_state ;
305+ state. selected = ( state. selected + 1 ) . min ( row_count. saturating_sub ( 1 ) ) ;
306+ }
307+ }
308+ KeyCode :: Up | KeyCode :: Char ( 'k' ) => {
309+ let state = & mut app. flamegraph_view . state . tree_view_state ;
310+ state. selected = state. selected . saturating_sub ( 1 ) ;
311+ }
312+ KeyCode :: Char ( 'G' ) => {
313+ if row_count > 0 {
314+ app. flamegraph_view . state . tree_view_state . selected = row_count. saturating_sub ( 1 ) ;
315+ }
316+ }
317+ KeyCode :: Char ( 'g' ) => {
318+ app. flamegraph_view . state . tree_view_state . selected = 0 ;
319+ }
320+ KeyCode :: Enter | KeyCode :: Right | KeyCode :: Char ( 'l' ) => {
321+ // Expand the selected node (or collapse if already expanded)
322+ let selected = app. flamegraph_view . state . tree_view_state . selected ;
323+ if let Some ( row) = rows. get ( selected) {
324+ if row. has_children {
325+ app. flamegraph_view
326+ . state
327+ . tree_view_state
328+ . toggle_expanded ( row. stack_id ) ;
329+ }
330+ }
331+ }
332+ KeyCode :: Left | KeyCode :: Char ( 'h' ) => {
333+ // Collapse the selected node, or move to parent
334+ let selected = app. flamegraph_view . state . tree_view_state . selected ;
335+ if let Some ( row) = rows. get ( selected) {
336+ if row. is_expanded {
337+ // Collapse it
338+ app. flamegraph_view
339+ . state
340+ . tree_view_state
341+ . expanded
342+ . remove ( & row. stack_id ) ;
343+ } else if row. depth > 0 {
344+ // Move cursor to parent (find the row with depth-1 above us)
345+ for i in ( 0 ..selected) . rev ( ) {
346+ if rows[ i] . depth < row. depth {
347+ app. flamegraph_view . state . tree_view_state . selected = i;
348+ break ;
349+ }
350+ }
351+ }
352+ }
353+ }
354+ KeyCode :: Esc => {
355+ // Collapse all and reset
356+ app. flamegraph_view . state . tree_view_state . expanded . clear ( ) ;
357+ }
358+ _ => {
359+ key_handled = false ;
360+ }
361+ }
362+ Ok ( key_handled)
363+ }
364+
231365pub fn handle_input_buffer ( key_event : KeyEvent , app : & mut App ) -> AppResult < ( ) > {
232366 if let Some ( input) = app. input_buffer . as_mut ( ) {
233367 match key_event. code {
0 commit comments