@@ -6,7 +6,6 @@ use crate::dbgp::client::ContinuationResponse;
66use crate :: dbgp:: client:: ContinuationStatus ;
77use crate :: dbgp:: client:: DbgpClient ;
88use crate :: dbgp:: client:: Property ;
9- use crate :: dbgp:: client:: StackGetResponse ;
109use crate :: event:: input:: AppEvent ;
1110use crate :: notification:: Notification ;
1211use crate :: theme:: Scheme ;
@@ -30,7 +29,6 @@ use ratatui::widgets::Block;
3029use ratatui:: widgets:: Padding ;
3130use ratatui:: widgets:: Paragraph ;
3231use ratatui:: Terminal ;
33- use tokio:: sync:: Notify ;
3432use std:: collections:: hash_map:: Entry ;
3533use std:: collections:: HashMap ;
3634use std:: io;
@@ -40,21 +38,65 @@ use tokio::net::TcpListener;
4038use tokio:: sync:: mpsc:: Receiver ;
4139use tokio:: sync:: mpsc:: Sender ;
4240use tokio:: sync:: Mutex ;
41+ use tokio:: sync:: Notify ;
4342use tokio:: task;
4443use tui_input:: Input ;
4544
46- type AnalyzedFiles = HashMap < String , Analysis > ;
45+ type AnalyzedFiles = HashMap < String , Analysis > ;
4746
4847#[ derive( Clone , Debug ) ]
49- pub struct HistoryEntry {
48+ pub struct StackFrame {
49+ pub level : u16 ,
5050 pub source : SourceContext ,
51- pub stack : StackGetResponse ,
52- pub context : ContextGetResponse ,
51+ pub context : Option < ContextGetResponse > ,
5352}
54- impl HistoryEntry {
55- // todo: this is inefficient!
53+ impl StackFrame {
5654 pub ( crate ) fn get_property ( & self , name : & str ) -> Option < & Property > {
57- self . context . properties . iter ( ) . find ( |& property| property. name == name)
55+ match & self . context {
56+ Some ( c) => c. properties . iter ( ) . find ( |& property| property. name == name) ,
57+ None => None ,
58+ }
59+ }
60+ }
61+
62+ #[ derive( Clone , Debug ) ]
63+ pub struct HistoryEntry {
64+ pub stacks : Vec < StackFrame > ,
65+ }
66+
67+ impl HistoryEntry {
68+ fn push ( & mut self , frame : StackFrame ) {
69+ self . stacks . push ( frame) ;
70+ }
71+ fn new ( ) -> Self {
72+ let stacks = Vec :: new ( ) ;
73+ HistoryEntry { stacks }
74+ }
75+
76+ fn initial ( filename : String , source : String ) -> HistoryEntry {
77+ HistoryEntry {
78+ stacks : vec ! [ StackFrame {
79+ level: 0 ,
80+ source: SourceContext {
81+ source,
82+ filename,
83+ line_no: 0 ,
84+ } ,
85+ context: None ,
86+ } ] ,
87+ }
88+ }
89+
90+ pub fn source ( & self , level : u16 ) -> SourceContext {
91+ let entry = self . stacks . get ( level as usize ) ;
92+ match entry {
93+ Some ( e) => e. source . clone ( ) ,
94+ None => SourceContext :: default ( ) ,
95+ }
96+ }
97+
98+ pub ( crate ) fn stack ( & self , stack_depth : u16 ) -> Option < & StackFrame > {
99+ self . stacks . get ( stack_depth as usize )
58100 }
59101}
60102
@@ -99,22 +141,14 @@ impl History {
99141 self . entries . get ( self . offset )
100142 }
101143
144+ pub ( crate ) fn current_mut ( & mut self ) -> Option < & mut HistoryEntry > {
145+ self . entries . get_mut ( self . offset )
146+ }
147+
102148 fn push ( & mut self , entry : HistoryEntry ) {
103149 self . entries . push ( entry) ;
104150 self . offset = self . entries . len ( ) - 1 ;
105151 }
106-
107- fn push_source ( & mut self , filename : String , source : String ) {
108- self . push ( HistoryEntry {
109- source : SourceContext {
110- source,
111- filename,
112- line_no : 1 ,
113- } ,
114- context : ContextGetResponse { properties : vec ! [ ] } ,
115- stack : StackGetResponse { entries : vec ! [ ] } ,
116- } ) ;
117- }
118152}
119153
120154#[ derive( Clone , Debug ) ]
@@ -123,6 +157,15 @@ pub struct SourceContext {
123157 pub filename : String ,
124158 pub line_no : u32 ,
125159}
160+ impl SourceContext {
161+ fn default ( ) -> SourceContext {
162+ SourceContext {
163+ source : "" . to_string ( ) ,
164+ filename : "" . to_string ( ) ,
165+ line_no : 0 ,
166+ }
167+ }
168+ }
126169
127170#[ derive( Debug , Clone ) ]
128171pub enum CurrentView {
@@ -157,6 +200,8 @@ pub struct App {
157200 pub theme : Theme ,
158201
159202 pub analyzed_files : AnalyzedFiles ,
203+
204+ pub stack_max_context_fetch : u16 ,
160205}
161206
162207impl App {
@@ -174,6 +219,7 @@ impl App {
174219 client : Arc :: new ( Mutex :: new ( client) ) ,
175220 counter : 0 ,
176221 context_depth : 4 ,
222+ stack_max_context_fetch : 1 ,
177223
178224 theme : Theme :: SolarizedDark ,
179225 server_status : None ,
@@ -304,8 +350,8 @@ impl App {
304350 let mut client = self . client . lock ( ) . await ;
305351 let response = client. deref_mut ( ) . connect ( s) . await ?;
306352 for ( feature, value) in [
307- ( "max_depth" , self . context_depth . to_string ( ) . as_str ( ) ) ,
308- ( "extended_properties" , "1" ) ,
353+ ( "max_depth" , self . context_depth . to_string ( ) . as_str ( ) ) ,
354+ ( "extended_properties" , "1" ) ,
309355 ] {
310356 info ! ( "setting feature {} to {:?}" , feature, value) ;
311357 client. feature_set ( feature, value) . await ?;
@@ -317,7 +363,8 @@ impl App {
317363 let source = client. source ( response. fileuri . clone ( ) ) . await . unwrap ( ) ;
318364
319365 self . history = History :: default ( ) ;
320- self . history . push_source ( response. fileuri . clone ( ) , source) ;
366+ self . history
367+ . push ( HistoryEntry :: initial ( response. fileuri . clone ( ) , source) ) ;
321368 }
322369 AppEvent :: Snapshot ( ) => {
323370 self . snapshot ( ) . await ?;
@@ -338,19 +385,33 @@ impl App {
338385 AppEvent :: ContextDepth ( inc) => {
339386 let depth = self . context_depth as i8 ;
340387 self . context_depth = depth. wrapping_add ( inc) . max ( 0 ) as u8 ;
341- self . client . lock ( ) . await . feature_set (
342- "max_depth" ,
343- self . context_depth . to_string ( ) . as_str ( )
344- ) . await ?;
345- } ,
388+ self . client
389+ . lock ( )
390+ . await
391+ . feature_set ( "max_depth" , self . context_depth . to_string ( ) . as_str ( ) )
392+ . await ?;
393+ }
346394 AppEvent :: ScrollSource ( amount) => {
347- self . session_view . source_scroll = apply_scroll ( self . session_view . source_scroll , amount, self . take_motion ( ) as i16 ) ;
395+ self . session_view . source_scroll = apply_scroll (
396+ self . session_view . source_scroll ,
397+ amount,
398+ self . take_motion ( ) as i16 ,
399+ ) ;
348400 }
349401 AppEvent :: ScrollContext ( amount) => {
350- self . session_view . context_scroll = apply_scroll ( self . session_view . context_scroll , amount, self . take_motion ( ) as i16 ) ;
402+ self . session_view . context_scroll = apply_scroll (
403+ self . session_view . context_scroll ,
404+ amount,
405+ self . take_motion ( ) as i16 ,
406+ ) ;
351407 }
352408 AppEvent :: ScrollStack ( amount) => {
353- self . session_view . stack_scroll = apply_scroll ( self . session_view . stack_scroll , amount, self . take_motion ( ) as i16 ) ;
409+ self . session_view . stack_scroll = apply_scroll (
410+ self . session_view . stack_scroll ,
411+ amount,
412+ self . take_motion ( ) as i16 ,
413+ ) ;
414+ self . populate_stack_context ( ) . await ?;
354415 }
355416 AppEvent :: ToggleFullscreen => {
356417 self . session_view . full_screen = !self . session_view . full_screen ;
@@ -369,17 +430,19 @@ impl App {
369430 . await ?;
370431 }
371432 AppEvent :: PushInputPlurality ( char) => self . input_plurality . push ( char) ,
372- AppEvent :: Input ( key_event) => {
373- match key_event. code {
374- KeyCode :: Char ( 't' ) => {
375- self . theme = self . theme . next ( ) ;
376- self . notification = Notification :: info ( format ! ( "Switched to theme: {:?}" , self . theme) ) ;
377- } ,
378- KeyCode :: Char ( '?' ) => {
379- self . sender . send ( AppEvent :: ChangeView ( CurrentView :: Help ) ) . await . unwrap ( ) ;
380- } ,
381- _ => self . send_event_to_current_view ( event) . await
433+ AppEvent :: Input ( key_event) => match key_event. code {
434+ KeyCode :: Char ( 't' ) => {
435+ self . theme = self . theme . next ( ) ;
436+ self . notification =
437+ Notification :: info ( format ! ( "Switched to theme: {:?}" , self . theme) ) ;
438+ }
439+ KeyCode :: Char ( '?' ) => {
440+ self . sender
441+ . send ( AppEvent :: ChangeView ( CurrentView :: Help ) )
442+ . await
443+ . unwrap ( ) ;
382444 }
445+ _ => self . send_event_to_current_view ( event) . await ,
383446 } ,
384447 _ => self . send_event_to_current_view ( event) . await ,
385448 } ;
@@ -400,7 +463,6 @@ impl App {
400463 tokio:: spawn ( async move {
401464 let mut last_response: Option < ContinuationResponse > = None ;
402465 for i in 0 ..count {
403-
404466 // we need to wait for the snapshot to complete before running a further
405467 // continuation.
406468 snapshot_notify. notified ( ) . await ;
@@ -477,41 +539,66 @@ impl App {
477539 pub async fn snapshot ( & mut self ) -> Result < ( ) > {
478540 let mut client = self . client . lock ( ) . await ;
479541 let stack = client. deref_mut ( ) . get_stack ( ) . await ?;
480- if let Some ( top) = stack. top_or_none ( ) {
481- let filename = & top. filename ;
482- let line_no = top. line ;
542+ let mut entry = HistoryEntry :: new ( ) ;
543+ for ( level, frame) in stack. entries . iter ( ) . enumerate ( ) {
544+ let filename = & frame. filename ;
545+ let line_no = frame. line ;
546+ let context = match ( level as u16 ) < self . stack_max_context_fetch {
547+ true => Some ( client. deref_mut ( ) . context_get ( level as u16 ) . await . unwrap ( ) ) ,
548+ false => None ,
549+ } ;
483550 let source_code = client
484551 . deref_mut ( )
485552 . source ( filename. to_string ( ) )
486553 . await
487554 . unwrap ( ) ;
555+
488556 let source = SourceContext {
489557 source : source_code,
490558 filename : filename. to_string ( ) ,
491559 line_no,
492560 } ;
493- let context = client . deref_mut ( ) . context_get ( ) . await . unwrap ( ) ;
494- match self . analyzed_files . entry ( source . filename . clone ( ) ) {
561+
562+ match self . analyzed_files . entry ( filename. clone ( ) ) {
495563 Entry :: Occupied ( _) => ( ) ,
496564 Entry :: Vacant ( vacant_entry) => {
497565 let mut analyser = Analyser :: new ( ) ;
498566 vacant_entry. insert ( analyser. analyze ( source. source . as_str ( ) ) . unwrap ( ) ) ;
499567 }
500568 } ;
501- let entry = HistoryEntry {
569+
570+ entry. push ( StackFrame {
571+ level : ( level as u16 ) ,
502572 source,
503- stack,
504573 context,
505- } ;
506- self . history . push ( entry) ;
507- self . session_view . reset ( ) ;
574+ } ) ;
508575 }
576+ self . history . push ( entry) ;
577+ self . session_view . reset ( ) ;
509578 Ok ( ( ) )
510579 }
511580
512581 pub ( crate ) fn theme ( & self ) -> Scheme {
513582 self . theme . scheme ( )
514583 }
584+
585+ async fn populate_stack_context ( & mut self ) -> Result < ( ) > {
586+ if !self . history . is_current ( ) {
587+ return Ok ( ( ) ) ;
588+ }
589+ let level = self . session_view . stack_scroll . 0 as usize ;
590+ if let Some ( c) = self . history . current_mut ( ) {
591+ let stack = c. stacks . get_mut ( level) ;
592+ if let Some ( s) = stack {
593+ if s. context . is_none ( ) {
594+ let mut client = self . client . lock ( ) . await ;
595+ let context = client. deref_mut ( ) . context_get ( level as u16 ) . await ?;
596+ s. context = Some ( context) ;
597+ }
598+ } ;
599+ } ;
600+ Ok ( ( ) )
601+ }
515602}
516603
517604fn apply_scroll ( scroll : ( u16 , u16 ) , amount : ( i16 , i16 ) , motion : i16 ) -> ( u16 , u16 ) {
0 commit comments