@@ -10,7 +10,7 @@ use crate::{
10
10
ui:: style:: { SharedTheme , Theme } ,
11
11
} ;
12
12
use anyhow:: Result ;
13
- use asyncgit:: sync:: Tags ;
13
+ use asyncgit:: sync:: { CommitId , Tags } ;
14
14
use chrono:: { DateTime , Local } ;
15
15
use crossterm:: event:: Event ;
16
16
use std:: {
@@ -33,6 +33,7 @@ pub struct CommitList {
33
33
branch : Option < String > ,
34
34
count_total : usize ,
35
35
items : ItemBatch ,
36
+ marked : Vec < CommitId > ,
36
37
scroll_state : ( Instant , f32 ) ,
37
38
tags : Option < Tags > ,
38
39
current_size : Cell < ( u16 , u16 ) > ,
@@ -50,6 +51,7 @@ impl CommitList {
50
51
) -> Self {
51
52
Self {
52
53
items : ItemBatch :: default ( ) ,
54
+ marked : Vec :: with_capacity ( 2 ) ,
53
55
selection : 0 ,
54
56
branch : None ,
55
57
count_total : 0 ,
@@ -164,6 +166,17 @@ impl CommitList {
164
166
Ok ( needs_update)
165
167
}
166
168
169
+ fn mark ( & mut self ) {
170
+ if let Some ( e) = self . selected_entry ( ) {
171
+ let id = e. id ;
172
+ if self . is_marked ( & id) . unwrap_or_default ( ) {
173
+ self . marked . retain ( |marked| marked != & id) ;
174
+ } else {
175
+ self . marked . push ( id) ;
176
+ }
177
+ }
178
+ }
179
+
167
180
fn update_scroll_speed ( & mut self ) {
168
181
const REPEATED_SCROLL_THRESHOLD_MILLIS : u128 = 300 ;
169
182
const SCROLL_SPEED_START : f32 = 0.1_f32 ;
@@ -188,21 +201,42 @@ impl CommitList {
188
201
self . scroll_state . 1 = speed. min ( SCROLL_SPEED_MAX ) ;
189
202
}
190
203
204
+ fn is_marked ( & self , id : & CommitId ) -> Option < bool > {
205
+ if self . marked . is_empty ( ) {
206
+ None
207
+ } else {
208
+ let found = self . marked . iter ( ) . any ( |entry| entry == id) ;
209
+ Some ( found)
210
+ }
211
+ }
212
+
191
213
fn get_entry_to_add < ' a > (
192
214
e : & ' a LogEntry ,
193
215
selected : bool ,
194
216
tags : Option < String > ,
195
217
theme : & Theme ,
196
218
width : usize ,
197
219
now : DateTime < Local > ,
220
+ marked : Option < bool > ,
198
221
) -> Spans < ' a > {
199
222
let mut txt: Vec < Span > = Vec :: new ( ) ;
200
- txt. reserve ( ELEMENTS_PER_LINE ) ;
223
+ txt. reserve (
224
+ ELEMENTS_PER_LINE + if marked. is_some ( ) { 2 } else { 0 } ,
225
+ ) ;
201
226
202
227
let splitter_txt = Cow :: from ( " " ) ;
203
228
let splitter =
204
229
Span :: styled ( splitter_txt, theme. text ( true , selected) ) ;
205
230
231
+ // marked
232
+ if let Some ( marked) = marked {
233
+ txt. push ( Span :: styled (
234
+ Cow :: from ( if marked { "X" } else { " " } ) ,
235
+ theme. text ( true , selected) ,
236
+ ) ) ;
237
+ txt. push ( splitter. clone ( ) ) ;
238
+ }
239
+
206
240
// commit hash
207
241
txt. push ( Span :: styled (
208
242
Cow :: from ( e. hash_short . as_str ( ) ) ,
@@ -258,6 +292,8 @@ impl CommitList {
258
292
259
293
let now = Local :: now ( ) ;
260
294
295
+ let any_marked = !self . marked . is_empty ( ) ;
296
+
261
297
for ( idx, e) in self
262
298
. items
263
299
. iter ( )
@@ -270,13 +306,21 @@ impl CommitList {
270
306
. as_ref ( )
271
307
. and_then ( |t| t. get ( & e. id ) )
272
308
. map ( |tags| tags. join ( " " ) ) ;
309
+
310
+ let marked = if any_marked {
311
+ self . is_marked ( & e. id )
312
+ } else {
313
+ None
314
+ } ;
315
+
273
316
txt. push ( Self :: get_entry_to_add (
274
317
e,
275
318
idx + self . scroll_top . get ( ) == selection,
276
319
tags,
277
320
& self . theme ,
278
321
width,
279
322
now,
323
+ marked,
280
324
) ) ;
281
325
}
282
326
@@ -368,6 +412,9 @@ impl Component for CommitList {
368
412
self . move_selection ( ScrollType :: PageUp ) ?
369
413
} else if k == self . key_config . page_down {
370
414
self . move_selection ( ScrollType :: PageDown ) ?
415
+ } else if k == self . key_config . log_mark_commit {
416
+ self . mark ( ) ;
417
+ true
371
418
} else {
372
419
false
373
420
} ;
0 commit comments