@@ -11,10 +11,14 @@ use crate::{
11
11
AsyncAppNotification , AsyncNotification ,
12
12
} ;
13
13
use anyhow:: Result ;
14
- use asyncgit:: sync:: { self , CommitId , RepoPathRef , TreeFile } ;
14
+ use asyncgit:: sync:: {
15
+ self , get_commit_info, CommitId , CommitInfo , RepoPathRef ,
16
+ TreeFile ,
17
+ } ;
15
18
use crossbeam_channel:: Sender ;
16
19
use crossterm:: event:: Event ;
17
20
use filetreelist:: { FileTree , FileTreeItem } ;
21
+ use std:: fmt:: Write ;
18
22
use std:: {
19
23
collections:: BTreeSet ,
20
24
convert:: From ,
@@ -27,6 +31,8 @@ use tui::{
27
31
widgets:: { Block , Borders } ,
28
32
Frame ,
29
33
} ;
34
+ use unicode_truncate:: UnicodeTruncateStr ;
35
+ use unicode_width:: UnicodeWidthStr ;
30
36
31
37
enum Focus {
32
38
Tree ,
@@ -43,7 +49,7 @@ pub struct RevisionFilesComponent {
43
49
tree : FileTree ,
44
50
scroll : VerticalScroll ,
45
51
visible : bool ,
46
- revision : Option < CommitId > ,
52
+ revision : Option < CommitInfo > ,
47
53
focus : Focus ,
48
54
key_config : SharedKeyConfig ,
49
55
}
@@ -82,23 +88,24 @@ impl RevisionFilesComponent {
82
88
self . show ( ) ?;
83
89
84
90
let same_id =
85
- self . revision . map ( |c| c == commit) . unwrap_or_default ( ) ;
91
+ self . revision . as_ref ( ) . map_or ( false , |c| c. id == commit) ;
86
92
if !same_id {
87
93
self . files =
88
94
sync:: tree_files ( & self . repo . borrow ( ) , commit) ?;
89
95
let filenames: Vec < & Path > =
90
96
self . files . iter ( ) . map ( |f| f. path . as_path ( ) ) . collect ( ) ;
91
97
self . tree = FileTree :: new ( & filenames, & BTreeSet :: new ( ) ) ?;
92
98
self . tree . collapse_but_root ( ) ;
93
- self . revision = Some ( commit) ;
99
+ self . revision =
100
+ Some ( get_commit_info ( & self . repo . borrow ( ) , & commit) ?) ;
94
101
}
95
102
96
103
Ok ( ( ) )
97
104
}
98
105
99
106
///
100
- pub const fn revision ( & self ) -> Option < CommitId > {
101
- self . revision
107
+ pub const fn revision ( & self ) -> Option < & CommitInfo > {
108
+ self . revision . as_ref ( )
102
109
}
103
110
104
111
///
@@ -161,7 +168,7 @@ impl RevisionFilesComponent {
161
168
self . queue . push ( InternalEvent :: OpenPopup (
162
169
StackablePopupOpen :: BlameFile ( BlameFileOpen {
163
170
file_path : path,
164
- commit_id : self . revision ,
171
+ commit_id : self . revision . as_ref ( ) . map ( |c| c . id ) ,
165
172
selection : None ,
166
173
} ) ,
167
174
) ) ;
@@ -260,12 +267,7 @@ impl RevisionFilesComponent {
260
267
261
268
let is_tree_focused = matches ! ( self . focus, Focus :: Tree ) ;
262
269
263
- let title = format ! (
264
- "Files at [{}]" ,
265
- self . revision
266
- . map( |c| c. get_short_string( ) )
267
- . unwrap_or_default( ) ,
268
- ) ;
270
+ let title = self . title_within ( tree_width) ;
269
271
ui:: draw_list_block (
270
272
f,
271
273
area,
@@ -283,6 +285,40 @@ impl RevisionFilesComponent {
283
285
self . scroll . draw ( f, area, & self . theme ) ;
284
286
}
285
287
}
288
+
289
+ fn title_within ( & self , tree_width : usize ) -> String {
290
+ let mut title = String :: from ( "Files at" ) ;
291
+ let message = self . revision . as_ref ( ) . and_then ( |c| {
292
+ let _ = write ! ( title, " {{{}}}" , c. id. get_short_string( ) ) ;
293
+
294
+ c. message . lines ( ) . next ( )
295
+ } ) ;
296
+
297
+ if let Some ( message) = message {
298
+ const ELLIPSIS : char = '\u{2026}' ; // …
299
+
300
+ let available = tree_width
301
+ . saturating_sub ( title. width ( ) )
302
+ . saturating_sub (
303
+ 2 /* frame end corners */ + 1 /* space */ + 2 , /* square brackets */
304
+ ) ;
305
+
306
+ if message. width ( ) <= available {
307
+ let _ = write ! ( title, " [{}]" , message) ;
308
+ } else if available > 1 {
309
+ let _ = write ! (
310
+ title,
311
+ " [{}{}]" ,
312
+ message. unicode_truncate( available - 1 ) . 0 ,
313
+ ELLIPSIS
314
+ ) ;
315
+ } else {
316
+ title. push ( ELLIPSIS ) ;
317
+ }
318
+ }
319
+
320
+ title
321
+ }
286
322
}
287
323
288
324
impl DrawableComponent for RevisionFilesComponent {
0 commit comments