@@ -3,7 +3,7 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEventKind};
3
3
use hashbrown:: HashSet ;
4
4
use napi:: bindgen_prelude:: External ;
5
5
use napi:: threadsafe_function:: { ErrorStrategy , ThreadsafeFunction } ;
6
- use ratatui:: layout:: { Alignment , Rect , Size } ;
6
+ use ratatui:: layout:: { Alignment , Position , Rect , Size } ;
7
7
use ratatui:: style:: Modifier ;
8
8
use ratatui:: style:: Style ;
9
9
use ratatui:: text:: { Line , Span } ;
@@ -14,6 +14,7 @@ use std::sync::{Arc, Mutex, RwLock};
14
14
use tokio:: sync:: mpsc;
15
15
use tokio:: sync:: mpsc:: UnboundedSender ;
16
16
use tracing:: { debug, trace} ;
17
+ use tui_logger:: { TuiLoggerSmartWidget , TuiLoggerWidget , TuiWidgetEvent , TuiWidgetState } ;
17
18
use vt100_ctt:: Parser ;
18
19
19
20
use crate :: native:: tui:: tui:: Tui ;
@@ -66,6 +67,8 @@ pub struct App {
66
67
selection_manager : Arc < Mutex < TaskSelectionManager > > ,
67
68
pinned_tasks : Vec < String > ,
68
69
tasks : Vec < Task > ,
70
+ debug_mode : bool ,
71
+ debug_state : TuiWidgetState ,
69
72
}
70
73
71
74
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
@@ -131,6 +134,8 @@ impl App {
131
134
pty_instances : HashMap :: new ( ) ,
132
135
selection_manager,
133
136
tasks,
137
+ debug_mode : false ,
138
+ debug_state : TuiWidgetState :: default ( ) ,
134
139
} )
135
140
}
136
141
@@ -292,7 +297,7 @@ impl App {
292
297
tui:: Event :: Render => action_tx. send ( Action :: Render ) ?,
293
298
tui:: Event :: Resize ( x, y) => action_tx. send ( Action :: Resize ( x, y) ) ?,
294
299
tui:: Event :: Key ( key) => {
295
- debug ! ( "Handling Key Event: {:?}" , key) ;
300
+ trace ! ( "Handling Key Event: {:?}" , key) ;
296
301
297
302
// Record that the user has interacted with the app
298
303
self . user_has_interacted = true ;
@@ -324,6 +329,16 @@ impl App {
324
329
} ;
325
330
}
326
331
332
+ if matches ! ( key. code, KeyCode :: F ( 12 ) ) {
333
+ self . dispatch_action ( Action :: ToggleDebugMode ) ;
334
+ return Ok ( false ) ;
335
+ }
336
+
337
+ if self . debug_mode {
338
+ self . handle_debug_event ( key) ;
339
+ return Ok ( false ) ;
340
+ }
341
+
327
342
// Only handle '?' key if we're not in interactive mode and the countdown popup is not open
328
343
if matches ! ( key. code, KeyCode :: Char ( '?' ) )
329
344
&& !self . is_interactive_mode ( )
@@ -729,7 +744,7 @@ impl App {
729
744
action_tx : & UnboundedSender < Action > ,
730
745
) {
731
746
if action != Action :: Tick && action != Action :: Render {
732
- debug ! ( "{action:?}" ) ;
747
+ trace ! ( "{action:?}" ) ;
733
748
}
734
749
match & action {
735
750
// Quit immediately
@@ -749,6 +764,10 @@ impl App {
749
764
// Ensure the pty instances get resized appropriately (debounced)
750
765
let _ = self . debounce_pty_resize ( ) ;
751
766
}
767
+ Action :: ToggleDebugMode => {
768
+ self . debug_mode = !self . debug_mode ;
769
+ debug ! ( "Debug mode: {}" , self . debug_mode) ;
770
+ }
752
771
Action :: Render => {
753
772
tui. draw ( |f| {
754
773
let area = f. area ( ) ;
@@ -764,6 +783,12 @@ impl App {
764
783
let frame_area = self . frame_area . unwrap ( ) ;
765
784
let layout_areas = self . layout_areas . as_mut ( ) . unwrap ( ) ;
766
785
786
+ if self . debug_mode {
787
+ let debug_widget = TuiLoggerSmartWidget :: default ( ) . state ( & self . debug_state ) ;
788
+ f. render_widget ( debug_widget, frame_area) ;
789
+ return ;
790
+ }
791
+
767
792
// TODO: move this to the layout manager?
768
793
// Check for minimum viable viewport size at the app level
769
794
if frame_area. height < 10 || frame_area. width < 40 {
@@ -1444,4 +1469,41 @@ impl App {
1444
1469
self . focus = focus;
1445
1470
self . dispatch_action ( Action :: UpdateFocus ( focus) ) ;
1446
1471
}
1472
+
1473
+ fn handle_debug_event ( & mut self , key : KeyEvent ) {
1474
+ // https://docs.rs/tui-logger/latest/tui_logger/#smart-widget-key-commands
1475
+ // | KEY | ACTION
1476
+ // |----------|-----------------------------------------------------------|
1477
+ // | h | Toggles target selector widget hidden/visible
1478
+ // | f | Toggle focus on the selected target only
1479
+ // | UP | Select previous target in target selector widget
1480
+ // | DOWN | Select next target in target selector widget
1481
+ // | LEFT | Reduce SHOWN (!) log messages by one level
1482
+ // | RIGHT | Increase SHOWN (!) log messages by one level
1483
+ // | - | Reduce CAPTURED (!) log messages by one level
1484
+ // | + | Increase CAPTURED (!) log messages by one level
1485
+ // | PAGEUP | Enter Page Mode and scroll approx. half page up in log history.
1486
+ // | PAGEDOWN | Only in page mode: scroll 10 events down in log history.
1487
+ // | ESCAPE | Exit page mode and go back to scrolling mode
1488
+ // | SPACE | Toggles hiding of targets, which have logfilter set to off
1489
+ let debug_widget_event = match key. code {
1490
+ KeyCode :: Char ( ' ' ) => Some ( TuiWidgetEvent :: SpaceKey ) ,
1491
+ KeyCode :: Esc => Some ( TuiWidgetEvent :: EscapeKey ) ,
1492
+ KeyCode :: PageUp => Some ( TuiWidgetEvent :: PrevPageKey ) ,
1493
+ KeyCode :: PageDown => Some ( TuiWidgetEvent :: NextPageKey ) ,
1494
+ KeyCode :: Up => Some ( TuiWidgetEvent :: UpKey ) ,
1495
+ KeyCode :: Down => Some ( TuiWidgetEvent :: DownKey ) ,
1496
+ KeyCode :: Left => Some ( TuiWidgetEvent :: LeftKey ) ,
1497
+ KeyCode :: Right => Some ( TuiWidgetEvent :: RightKey ) ,
1498
+ KeyCode :: Char ( '+' ) => Some ( TuiWidgetEvent :: PlusKey ) ,
1499
+ KeyCode :: Char ( '-' ) => Some ( TuiWidgetEvent :: MinusKey ) ,
1500
+ KeyCode :: Char ( 'h' ) => Some ( TuiWidgetEvent :: HideKey ) ,
1501
+ KeyCode :: Char ( 'f' ) => Some ( TuiWidgetEvent :: FocusKey ) ,
1502
+ _ => None ,
1503
+ } ;
1504
+
1505
+ if let Some ( event) = debug_widget_event {
1506
+ self . debug_state . transition ( event) ;
1507
+ }
1508
+ }
1447
1509
}
0 commit comments