@@ -5,12 +5,13 @@ use crate::dbgp::client::ContextGetResponse;
55use crate :: dbgp:: client:: ContinuationResponse ;
66use crate :: dbgp:: client:: ContinuationStatus ;
77use crate :: dbgp:: client:: DbgpClient ;
8+ use crate :: dbgp:: client:: EvalResponse ;
89use crate :: dbgp:: client:: Property ;
910use crate :: event:: input:: AppEvent ;
1011use crate :: notification:: Notification ;
1112use crate :: theme:: Scheme ;
1213use crate :: theme:: Theme ;
13- use crate :: view:: eval:: draw_properties ;
14+ use crate :: view:: eval:: EvalDialog ;
1415use crate :: view:: help:: HelpView ;
1516use crate :: view:: layout:: LayoutView ;
1617use crate :: view:: listen:: ListenView ;
@@ -21,14 +22,13 @@ use crate::view::View;
2122use crate :: workspace:: Workspace ;
2223use anyhow:: Result ;
2324use crossterm:: event:: KeyCode ;
25+ use log:: error;
2426use log:: info;
2527use log:: warn;
26- use log:: error;
2728use ratatui:: layout:: Rect ;
2829use ratatui:: prelude:: CrosstermBackend ;
2930use ratatui:: style:: Color ;
3031use ratatui:: style:: Style ;
31- use ratatui:: text:: Line ;
3232use ratatui:: widgets:: Block ;
3333use ratatui:: widgets:: Padding ;
3434use ratatui:: widgets:: Paragraph ;
@@ -66,6 +66,13 @@ impl StackFrame {
6666#[ derive( Clone , Debug ) ]
6767pub struct HistoryEntry {
6868 pub stacks : Vec < StackFrame > ,
69+ pub eval : Option < EvalEntry > ,
70+ }
71+
72+ #[ derive( Clone , Debug ) ]
73+ pub struct EvalEntry {
74+ pub expr : String ,
75+ pub response : EvalResponse ,
6976}
7077
7178impl HistoryEntry {
@@ -74,7 +81,7 @@ impl HistoryEntry {
7481 }
7582 fn new ( ) -> Self {
7683 let stacks = Vec :: new ( ) ;
77- HistoryEntry { stacks }
84+ HistoryEntry { stacks, eval : None }
7885 }
7986
8087 fn initial ( filename : String , source : String ) -> HistoryEntry {
@@ -88,6 +95,7 @@ impl HistoryEntry {
8895 } ,
8996 context: None ,
9097 } ] ,
98+ eval : None ,
9199 }
92100 }
93101
@@ -178,6 +186,11 @@ pub enum SelectedView {
178186 Help ,
179187}
180188
189+ #[ derive( Debug , Clone ) ]
190+ pub enum ActiveDialog {
191+ Eval ,
192+ }
193+
181194#[ derive( PartialEq ) ]
182195pub enum ListenStatus {
183196 Connected ,
@@ -189,7 +202,6 @@ impl ListenStatus {
189202 pub fn is_connected ( & self ) -> bool {
190203 * self == ListenStatus :: Connected
191204 }
192-
193205}
194206
195207pub struct App {
@@ -213,6 +225,7 @@ pub struct App {
213225 pub view_current : SelectedView ,
214226 pub focus_view : bool ,
215227 pub session_view : SessionViewState ,
228+ pub active_dialog : Option < ActiveDialog > ,
216229 pub input_plurality : Vec < char > ,
217230
218231 pub counter : u16 ,
@@ -251,6 +264,7 @@ impl App {
251264 command_input : Input :: default ( ) ,
252265 command_response : None ,
253266 view_current : SelectedView :: Listen ,
267+ active_dialog : None ,
254268 focus_view : false ,
255269 session_view : SessionViewState :: new ( ) ,
256270
@@ -285,15 +299,10 @@ impl App {
285299
286300 loop {
287301 match listener. accept ( ) . await {
288- Ok ( s) => {
289- match sender. send ( AppEvent :: ClientConnected ( s. 0 ) ) . await {
290- Ok ( _) => ( ) ,
291- Err ( e) => error ! (
292- "Could not send connection event: {}" ,
293- e
294- ) ,
295- }
296- }
302+ Ok ( s) => match sender. send ( AppEvent :: ClientConnected ( s. 0 ) ) . await {
303+ Ok ( _) => ( ) ,
304+ Err ( e) => error ! ( "Could not send connection event: {}" , e) ,
305+ } ,
297306 Err ( _) => panic ! ( "Could not connect" ) ,
298307 }
299308 }
@@ -311,6 +320,7 @@ impl App {
311320 let event = event. unwrap ( ) ;
312321
313322 if let Err ( e) = self . handle_event ( terminal, event) . await {
323+ self . active_dialog = None ;
314324 self . notification = Notification :: error ( e. to_string ( ) ) ;
315325 continue ;
316326 } ;
@@ -334,7 +344,7 @@ impl App {
334344 match event {
335345 AppEvent :: Tick => {
336346 self . tick = self . tick . wrapping_add ( 1 ) ;
337- } ,
347+ }
338348 _ => info ! ( "Handling event {:?}" , event) ,
339349 } ;
340350 match event {
@@ -374,7 +384,9 @@ impl App {
374384 for _ in 0 ..self . take_motion ( ) {
375385 self . history . next ( ) ;
376386 self . recenter ( ) ;
377- if self . history . is_current ( ) && ( self . listening_status == ListenStatus :: Connected ) {
387+ if self . history . is_current ( )
388+ && ( self . listening_status == ListenStatus :: Connected )
389+ {
378390 self . sender
379391 . send ( AppEvent :: ChangeSessionViewMode ( SessionViewMode :: Current ) )
380392 . await ?;
@@ -392,10 +404,11 @@ impl App {
392404 self . view_current = SelectedView :: Listen ;
393405 self . session_view . mode = SessionViewMode :: Current ;
394406 self . notification = Notification :: info ( "listening for next connection" . to_string ( ) )
395- } ,
407+ }
396408 AppEvent :: ClientConnected ( s) => {
397409 if self . listening_status != ListenStatus :: Listening {
398- self . notification = Notification :: warning ( "refused incoming connection" . to_string ( ) ) ;
410+ self . notification =
411+ Notification :: warning ( "refused incoming connection" . to_string ( ) ) ;
399412 } else {
400413 self . notification = Notification :: info ( "connected" . to_string ( ) ) ;
401414 let filepath = {
@@ -437,7 +450,7 @@ impl App {
437450 }
438451 AppEvent :: ContextDepth ( inc) => {
439452 let depth = self . context_depth ;
440- self . context_depth = depth. wrapping_add ( inc as u16 ) . max ( 0 ) ;
453+ self . context_depth = depth. wrapping_add ( inc as u16 ) ;
441454 self . client
442455 . lock ( )
443456 . await
@@ -447,11 +460,11 @@ impl App {
447460 AppEvent :: ContextFilterOpen => {
448461 self . session_view . context_filter . show = true ;
449462 self . focus_view = true ;
450- } ,
463+ }
451464 AppEvent :: ContextSearchClose => {
452465 self . session_view . context_filter . show = false ;
453466 self . focus_view = false ;
454- } ,
467+ }
455468 AppEvent :: ScrollSource ( amount) => {
456469 self . session_view . source_scroll = apply_scroll (
457470 self . session_view . source_scroll ,
@@ -466,6 +479,13 @@ impl App {
466479 self . take_motion ( ) as i16 ,
467480 ) ;
468481 }
482+ AppEvent :: ScrollEval ( amount) => {
483+ self . session_view . eval_state . scroll = apply_scroll (
484+ self . session_view . eval_state . scroll ,
485+ amount,
486+ self . take_motion ( ) as i16 ,
487+ ) ;
488+ }
469489 AppEvent :: ScrollStack ( amount) => {
470490 self . session_view . stack_scroll = apply_scroll (
471491 self . session_view . stack_scroll ,
@@ -493,29 +513,39 @@ impl App {
493513 }
494514 AppEvent :: PushInputPlurality ( char) => self . input_plurality . push ( char) ,
495515 AppEvent :: EvalStart => {
496- self . session_view . eval_state . active = true ;
497- self . focus_view = true ;
498- } ,
516+ if !self . history . is_current ( ) {
517+ self . notification =
518+ Notification :: warning ( "Cannot eval in history mode" . to_string ( ) ) ;
519+ } else {
520+ self . active_dialog = Some ( ActiveDialog :: Eval ) ;
521+ }
522+ }
499523 AppEvent :: EvalCancel => {
500- self . session_view . eval_state . active = false ;
501- self . focus_view = false ;
502- } ,
524+ self . active_dialog = None ;
525+ }
503526 AppEvent :: EvalExecute => {
504- self . session_view . eval_state . active = false ;
505- self . focus_view = false ;
506- let response = self . client
507- . lock ( )
508- . await
509- . eval (
510- self . session_view . eval_state . input . to_string ( ) ,
511- self . session_view . stack_depth ( )
512- )
513- . await ?;
527+ if self . session_view . eval_state . input . to_string ( ) . is_empty ( ) {
528+ self . session_view . eval_state . response = None ;
529+ } else {
530+ let response = self
531+ . client
532+ . lock ( )
533+ . await
534+ . eval (
535+ self . session_view . eval_state . input . to_string ( ) ,
536+ self . session_view . stack_depth ( ) ,
537+ )
538+ . await ?;
514539
515- self . session_view . eval_state . properties = response. properties ;
516- } ,
540+ self . session_view . eval_state . response = Some ( response) ;
541+ self . sender . send ( AppEvent :: Snapshot ( ) ) . await . unwrap ( ) ;
542+ }
543+ self . active_dialog = None ;
544+ }
517545 AppEvent :: Input ( key_event) => {
518- if self . focus_view {
546+ if self . active_dialog . is_some ( ) {
547+ self . send_event_to_current_dialog ( event) . await ;
548+ } else if self . focus_view {
519549 // event shandled exclusively by view (e.g. input needs focus)
520550 self . send_event_to_current_view ( event) . await ;
521551 } else {
@@ -535,7 +565,7 @@ impl App {
535565 _ => self . send_event_to_current_view ( event) . await ,
536566 }
537567 }
538- } ,
568+ }
539569 _ => self . send_event_to_current_view ( event) . await ,
540570 } ;
541571
@@ -599,6 +629,17 @@ impl App {
599629 } ) ;
600630 }
601631
632+ async fn send_event_to_current_dialog ( & mut self , event : AppEvent ) {
633+ if let Some ( dialog) = & self . active_dialog {
634+ let subsequent_event = match & dialog {
635+ ActiveDialog :: Eval => EvalDialog :: handle ( self , event) ,
636+ } ;
637+ if let Some ( event) = subsequent_event {
638+ self . sender . send ( event) . await . unwrap ( )
639+ } ;
640+ }
641+ }
642+
602643 // route the event to the currently selected view
603644 async fn send_event_to_current_view ( & mut self , event : AppEvent ) {
604645 let subsequent_event = match self . view_current {
@@ -629,16 +670,21 @@ impl App {
629670
630671 /// capture the current status and push it onto the history stack
631672 pub async fn snapshot ( & mut self ) -> Result < ( ) > {
632- let stack = {
633- self . client . lock ( ) . await . deref_mut ( ) . get_stack ( ) . await ?
634- } ;
673+ let stack = { self . client . lock ( ) . await . deref_mut ( ) . get_stack ( ) . await ? } ;
635674 let mut entry = HistoryEntry :: new ( ) ;
636675 for ( level, frame) in stack. entries . iter ( ) . enumerate ( ) {
637676 let filename = & frame. filename ;
638677 let line_no = frame. line ;
639678 let context = {
640679 match ( level as u16 ) < self . stack_max_context_fetch {
641- true => Some ( self . client . lock ( ) . await . deref_mut ( ) . context_get ( level as u16 ) . await ?) ,
680+ true => Some (
681+ self . client
682+ . lock ( )
683+ . await
684+ . deref_mut ( )
685+ . context_get ( level as u16 )
686+ . await ?,
687+ ) ,
642688 false => None ,
643689 }
644690 } ;
@@ -664,6 +710,28 @@ impl App {
664710 context,
665711 } ) ;
666712 }
713+
714+ // *xdebug* only evalutes expressions on the current stack frame
715+ let eval = if !self . session_view . eval_state . input . to_string ( ) . is_empty ( ) {
716+ let response = self
717+ . client
718+ . lock ( )
719+ . await
720+ . eval (
721+ self . session_view . eval_state . input . to_string ( ) ,
722+ self . session_view . stack_depth ( ) ,
723+ )
724+ . await ?;
725+
726+ Some ( EvalEntry {
727+ expr : self . session_view . eval_state . input . to_string ( ) ,
728+ response
729+ } )
730+ } else {
731+ None
732+ } ;
733+
734+ entry. eval = eval;
667735 self . session_view . reset ( ) ;
668736 self . history . push ( entry) ;
669737 self . recenter ( ) ;
@@ -702,7 +770,10 @@ impl App {
702770
703771 fn recenter ( & mut self ) {
704772 let entry = self . history . current ( ) ;
705- if let Some ( entry) = entry { self . session_view . scroll_to_line ( entry. source ( self . session_view . stack_depth ( ) ) . line_no ) }
773+ if let Some ( entry) = entry {
774+ self . session_view
775+ . scroll_to_line ( entry. source ( self . session_view . stack_depth ( ) ) . line_no )
776+ }
706777 }
707778}
708779
0 commit comments