@@ -93,7 +93,7 @@ pub struct BlameFilePopup {
93
93
table_state : std:: cell:: Cell < TableState > ,
94
94
key_config : SharedKeyConfig ,
95
95
current_height : std:: cell:: Cell < usize > ,
96
- blame : Option < BlameProcess > ,
96
+ blame_stack : Vec < BlameProcess > ,
97
97
app_sender : Sender < AsyncAppNotification > ,
98
98
git_sender : Sender < AsyncGitNotification > ,
99
99
repo : RepoPathRef ,
@@ -123,7 +123,7 @@ impl DrawableComponent for BlameFilePopup {
123
123
] ;
124
124
125
125
let number_of_rows: usize = rows. len ( ) ;
126
- let syntax_highlight_progress = match self . blame {
126
+ let syntax_highlight_progress = match self . blame_stack . last ( ) {
127
127
Some ( BlameProcess :: SyntaxHighlighting {
128
128
ref job,
129
129
..
@@ -193,10 +193,7 @@ impl Component for BlameFilePopup {
193
193
out : & mut Vec < CommandInfo > ,
194
194
force_all : bool ,
195
195
) -> CommandBlocking {
196
- let has_result = self
197
- . blame
198
- . as_ref ( )
199
- . is_some_and ( |blame| blame. result ( ) . is_some ( ) ) ;
196
+ let has_result = self . blame_stack . last ( ) . is_some_and ( |last| last. result ( ) . is_some ( ) ) ;
200
197
if self . is_visible ( ) || force_all {
201
198
out. push (
202
199
CommandInfo :: new (
@@ -307,8 +304,40 @@ impl Component for BlameFilePopup {
307
304
) ,
308
305
) ) ;
309
306
}
307
+ } else if key_match (
308
+ key,
309
+ self . key_config . keys . blame ,
310
+ ) {
311
+ if let Some ( file_path) = self
312
+ . params
313
+ . as_ref ( )
314
+ . map ( |p| p. file_path . clone ( ) )
315
+ {
316
+ let _ = self . open ( BlameFileOpen {
317
+ file_path,
318
+ commit_id : self . selected_commit ( ) ,
319
+ selection : self . get_selection ( ) ,
320
+ } ) ;
321
+ }
322
+ } else if key_match (
323
+ key,
324
+ self . key_config . keys . blame_back ,
325
+ ) {
326
+ match self . blame_stack . len ( ) {
327
+ 0 => {
328
+ self . hide_stacked ( false )
329
+ } ,
330
+ 1 => {
331
+ self . blame_stack . pop ( ) ;
332
+ self . hide_stacked ( false )
333
+ } ,
334
+ _ => {
335
+ self . blame_stack . pop ( ) ;
336
+ } ,
337
+ }
310
338
}
311
339
340
+
312
341
return Ok ( EventState :: Consumed ) ;
313
342
}
314
343
}
@@ -342,7 +371,7 @@ impl BlameFilePopup {
342
371
current_height : std:: cell:: Cell :: new ( 0 ) ,
343
372
app_sender : env. sender_app . clone ( ) ,
344
373
git_sender : env. sender_git . clone ( ) ,
345
- blame : None ,
374
+ blame_stack : vec ! [ ] ,
346
375
repo : env. repo . clone ( ) ,
347
376
}
348
377
}
@@ -371,11 +400,12 @@ impl BlameFilePopup {
371
400
file_path : open. file_path ,
372
401
commit_id : open. commit_id ,
373
402
} ) ;
374
- self . blame =
375
- Some ( BlameProcess :: GettingBlame ( AsyncBlame :: new (
403
+ self . blame_stack . push (
404
+ BlameProcess :: GettingBlame ( AsyncBlame :: new (
376
405
self . repo . borrow ( ) . clone ( ) ,
377
406
& self . git_sender ,
378
- ) ) ) ;
407
+ ) )
408
+ ) ;
379
409
self . table_state . get_mut ( ) . select ( Some ( 0 ) ) ;
380
410
self . visible = true ;
381
411
self . update ( ) ?;
@@ -384,9 +414,8 @@ impl BlameFilePopup {
384
414
}
385
415
386
416
///
387
- pub const fn any_work_pending ( & self ) -> bool {
388
- self . blame . is_some ( )
389
- && !matches ! ( self . blame, Some ( BlameProcess :: Result ( _) ) )
417
+ pub fn any_work_pending ( & self ) -> bool {
418
+ self . blame_stack . last ( ) . is_some_and ( |last| last. result ( ) . is_some ( ) )
390
419
}
391
420
392
421
pub fn update_async (
@@ -416,7 +445,7 @@ impl BlameFilePopup {
416
445
if self . is_visible ( ) {
417
446
if let Some ( BlameProcess :: GettingBlame (
418
447
ref mut async_blame,
419
- ) ) = self . blame
448
+ ) ) = self . blame_stack . last_mut ( )
420
449
{
421
450
if let Some ( params) = & self . params {
422
451
if let Some ( (
@@ -425,19 +454,17 @@ impl BlameFilePopup {
425
454
) ) = async_blame. last ( ) ?
426
455
{
427
456
if previous_blame_params == * params {
428
- self . blame = Some (
429
- BlameProcess :: SyntaxHighlighting {
430
- unstyled_file_blame :
431
- SyntaxFileBlame {
432
- file_blame :
433
- last_file_blame,
434
- styled_text : None ,
435
- } ,
436
- job : AsyncSingleJob :: new (
437
- self . app_sender . clone ( ) ,
438
- ) ,
439
- } ,
440
- ) ;
457
+ * self . blame_stack . last_mut ( ) . unwrap ( ) = BlameProcess :: SyntaxHighlighting {
458
+ unstyled_file_blame :
459
+ SyntaxFileBlame {
460
+ file_blame :
461
+ last_file_blame,
462
+ styled_text : None ,
463
+ } ,
464
+ job : AsyncSingleJob :: new (
465
+ self . app_sender . clone ( ) ,
466
+ ) ,
467
+ } ;
441
468
self . set_open_selection ( ) ;
442
469
self . highlight_blame_lines ( ) ;
443
470
@@ -457,7 +484,7 @@ impl BlameFilePopup {
457
484
let Some ( BlameProcess :: SyntaxHighlighting {
458
485
ref unstyled_file_blame,
459
486
ref job,
460
- } ) = self . blame
487
+ } ) = self . blame_stack . last ( )
461
488
else {
462
489
return ;
463
490
} ;
@@ -474,16 +501,15 @@ impl BlameFilePopup {
474
501
== Path :: new (
475
502
unstyled_file_blame. path ( ) ,
476
503
) {
477
- self . blame =
478
- Some ( BlameProcess :: Result (
479
- SyntaxFileBlame {
480
- file_blame :
481
- unstyled_file_blame
482
- . file_blame
483
- . clone ( ) ,
484
- styled_text : Some ( syntax) ,
485
- } ,
486
- ) ) ;
504
+ * self . blame_stack . last_mut ( ) . unwrap ( ) = BlameProcess :: Result (
505
+ SyntaxFileBlame {
506
+ file_blame :
507
+ unstyled_file_blame
508
+ . file_blame
509
+ . clone ( ) ,
510
+ styled_text : Some ( syntax) ,
511
+ } ,
512
+ ) ;
487
513
}
488
514
}
489
515
}
@@ -498,7 +524,7 @@ impl BlameFilePopup {
498
524
match (
499
525
self . any_work_pending ( ) ,
500
526
self . params . as_ref ( ) ,
501
- self . blame . as_ref ( ) . and_then ( |blame| blame. result ( ) ) ,
527
+ self . blame_stack . last ( ) . and_then ( |blame| blame. result ( ) ) ,
502
528
) {
503
529
( true , Some ( params) , _) => {
504
530
format ! (
@@ -526,8 +552,7 @@ impl BlameFilePopup {
526
552
527
553
///
528
554
fn get_rows ( & self , width : usize ) -> Vec < Row > {
529
- self . blame
530
- . as_ref ( )
555
+ self . blame_stack . last ( )
531
556
. and_then ( |blame| blame. result ( ) )
532
557
. map ( |file_blame| {
533
558
let styled_text: Option < Text < ' _ > > = file_blame
@@ -556,7 +581,7 @@ impl BlameFilePopup {
556
581
let Some ( BlameProcess :: SyntaxHighlighting {
557
582
ref unstyled_file_blame,
558
583
ref mut job,
559
- } ) = self . blame
584
+ } ) = self . blame_stack . last_mut ( )
560
585
else {
561
586
return ;
562
587
} ;
@@ -654,7 +679,7 @@ impl BlameFilePopup {
654
679
} ) ;
655
680
656
681
let file_blame =
657
- self . blame . as_ref ( ) . and_then ( |blame| blame. result ( ) ) ;
682
+ self . blame_stack . last ( ) . and_then ( |blame| blame. result ( ) ) ;
658
683
let is_blamed_commit = file_blame
659
684
. and_then ( |file_blame| {
660
685
blame_hunk. map ( |hunk| {
@@ -673,8 +698,8 @@ impl BlameFilePopup {
673
698
}
674
699
675
700
fn get_max_line_number ( & self ) -> usize {
676
- self . blame
677
- . as_ref ( )
701
+ self . blame_stack
702
+ . last ( )
678
703
. and_then ( |blame| blame. result ( ) )
679
704
. map_or ( 0 , |file_blame| file_blame. lines ( ) . len ( ) - 1 )
680
705
}
@@ -727,8 +752,8 @@ impl BlameFilePopup {
727
752
}
728
753
729
754
fn get_selection ( & self ) -> Option < usize > {
730
- self . blame
731
- . as_ref ( )
755
+ self . blame_stack
756
+ . last ( )
732
757
. and_then ( |blame| blame. result ( ) )
733
758
. and_then ( |_| {
734
759
let table_state = self . table_state . take ( ) ;
@@ -742,8 +767,8 @@ impl BlameFilePopup {
742
767
}
743
768
744
769
fn selected_commit ( & self ) -> Option < CommitId > {
745
- self . blame
746
- . as_ref ( )
770
+ self . blame_stack
771
+ . last ( )
747
772
. and_then ( |blame| blame. result ( ) )
748
773
. and_then ( |file_blame| {
749
774
let table_state = self . table_state . take ( ) ;
0 commit comments