1
- use super :: { CommandBlocking , DrawableComponent , ScrollType } ;
1
+ use super :: {
2
+ CommandBlocking , DrawableComponent , ExtendType , ScrollType ,
3
+ } ;
2
4
use crate :: {
3
5
components:: { CommandInfo , Component } ,
4
6
keys,
@@ -27,11 +29,41 @@ struct Current {
27
29
hash : u64 ,
28
30
}
29
31
32
+ ///
33
+ #[ derive( Clone , Copy ) ]
34
+ enum Selection {
35
+ Single ( usize ) ,
36
+ Multiple ( usize , usize ) ,
37
+ }
38
+
39
+ impl Selection {
40
+ fn get_start ( & self ) -> usize {
41
+ match self {
42
+ Self :: Single ( start) | Self :: Multiple ( start, _) => * start,
43
+ }
44
+ }
45
+
46
+ fn get_end ( & self ) -> usize {
47
+ match self {
48
+ Self :: Single ( end) | Self :: Multiple ( _, end) => * end,
49
+ }
50
+ }
51
+
52
+ fn contains ( & self , index : usize ) -> bool {
53
+ match self {
54
+ Self :: Single ( start) => index == * start,
55
+ Self :: Multiple ( start, end) => {
56
+ * start <= index && index <= * end
57
+ }
58
+ }
59
+ }
60
+ }
61
+
30
62
///
31
63
pub struct DiffComponent {
32
64
diff : Option < FileDiff > ,
33
65
pending : bool ,
34
- selection : usize ,
66
+ selection : Selection ,
35
67
selected_hunk : Option < usize > ,
36
68
current_size : Cell < ( u16 , u16 ) > ,
37
69
focused : bool ,
@@ -52,7 +84,7 @@ impl DiffComponent {
52
84
selected_hunk : None ,
53
85
diff : None ,
54
86
current_size : Cell :: new ( ( 0 , 0 ) ) ,
55
- selection : 0 ,
87
+ selection : Selection :: Single ( 0 ) ,
56
88
scroll_top : Cell :: new ( 0 ) ,
57
89
theme,
58
90
}
@@ -73,7 +105,7 @@ impl DiffComponent {
73
105
self . current = Current :: default ( ) ;
74
106
self . diff = None ;
75
107
self . scroll_top . set ( 0 ) ;
76
- self . selection = 0 ;
108
+ self . selection = Selection :: Single ( 0 ) ;
77
109
self . selected_hunk = None ;
78
110
self . pending = pending;
79
111
@@ -97,12 +129,14 @@ impl DiffComponent {
97
129
hash,
98
130
} ;
99
131
100
- self . selected_hunk =
101
- Self :: find_selected_hunk ( & diff, self . selection ) ?;
132
+ self . selected_hunk = Self :: find_selected_hunk (
133
+ & diff,
134
+ self . selection . get_start ( ) ,
135
+ ) ?;
102
136
103
137
self . diff = Some ( diff) ;
104
138
self . scroll_top . set ( 0 ) ;
105
- self . selection = 0 ;
139
+ self . selection = Selection :: Single ( 0 ) ;
106
140
}
107
141
108
142
Ok ( ( ) )
@@ -113,37 +147,61 @@ impl DiffComponent {
113
147
move_type : ScrollType ,
114
148
) -> Result < ( ) > {
115
149
if let Some ( diff) = & self . diff {
116
- let old = self . selection ;
150
+ let old_start = self . selection . get_start ( ) ;
117
151
118
152
let max = diff. lines . saturating_sub ( 1 ) as usize ;
119
153
120
- self . selection = match move_type {
121
- ScrollType :: Down => old . saturating_add ( 1 ) ,
122
- ScrollType :: Up => old . saturating_sub ( 1 ) ,
154
+ let new_start = match move_type {
155
+ ScrollType :: Down => old_start . saturating_add ( 1 ) ,
156
+ ScrollType :: Up => old_start . saturating_sub ( 1 ) ,
123
157
ScrollType :: Home => 0 ,
124
158
ScrollType :: End => max,
125
- ScrollType :: PageDown => {
126
- self . selection . saturating_add (
127
- self . current_size . get ( ) . 1 . saturating_sub ( 1 )
128
- as usize ,
129
- )
130
- }
131
- ScrollType :: PageUp => self . selection . saturating_sub (
159
+ ScrollType :: PageDown => old_start. saturating_add (
160
+ self . current_size . get ( ) . 1 . saturating_sub ( 1 )
161
+ as usize ,
162
+ ) ,
163
+ ScrollType :: PageUp => old_start. saturating_sub (
132
164
self . current_size . get ( ) . 1 . saturating_sub ( 1 )
133
165
as usize ,
134
166
) ,
135
167
} ;
136
168
137
- self . selection = cmp:: min ( max, self . selection ) ;
169
+ self . selection =
170
+ Selection :: Single ( cmp:: min ( max, new_start) ) ;
138
171
139
- if old != self . selection {
172
+ if new_start != old_start {
140
173
self . selected_hunk =
141
- Self :: find_selected_hunk ( diff, self . selection ) ?;
174
+ Self :: find_selected_hunk ( diff, new_start ) ?;
142
175
}
143
176
}
144
177
Ok ( ( ) )
145
178
}
146
179
180
+ fn extend_selection (
181
+ & mut self ,
182
+ extend_type : ExtendType ,
183
+ ) -> Result < ( ) > {
184
+ if let Some ( diff) = & self . diff {
185
+ let max = diff. lines . saturating_sub ( 1 ) as usize ;
186
+ let start = self . selection . get_start ( ) ;
187
+ let old_end = self . selection . get_end ( ) ;
188
+
189
+ self . selection = match extend_type {
190
+ ExtendType :: Up => Selection :: Multiple (
191
+ start,
192
+ cmp:: max ( start, old_end. saturating_sub ( 1 ) ) ,
193
+ ) ,
194
+
195
+ ExtendType :: Down => Selection :: Multiple (
196
+ start,
197
+ cmp:: min ( old_end + 1 , max) ,
198
+ ) ,
199
+ } ;
200
+ }
201
+
202
+ Ok ( ( ) )
203
+ }
204
+
147
205
fn find_selected_hunk (
148
206
diff : & FileDiff ,
149
207
line_selected : usize ,
@@ -210,8 +268,6 @@ impl DiffComponent {
210
268
Text :: Raw ( Cow :: from( ")" ) ) ,
211
269
] ) ;
212
270
} else {
213
- let selection = self . selection ;
214
-
215
271
let min = self . scroll_top . get ( ) ;
216
272
let max = min + height as usize ;
217
273
@@ -242,7 +298,8 @@ impl DiffComponent {
242
298
& mut res,
243
299
width,
244
300
line,
245
- selection == line_cursor,
301
+ self . selection
302
+ . contains ( line_cursor) ,
246
303
hunk_selected,
247
304
i == hunk_len as usize - 1 ,
248
305
& self . theme ,
@@ -432,7 +489,7 @@ impl DrawableComponent for DiffComponent {
432
489
self . scroll_top . set ( calc_scroll_top (
433
490
self . scroll_top . get ( ) ,
434
491
self . current_size . get ( ) . 1 as usize ,
435
- self . selection ,
492
+ self . selection . get_start ( ) ,
436
493
) ) ;
437
494
438
495
let title =
@@ -512,11 +569,19 @@ impl Component for DiffComponent {
512
569
self . move_selection ( ScrollType :: Down ) ?;
513
570
Ok ( true )
514
571
}
515
- keys:: SHIFT_DOWN | keys:: END => {
572
+ keys:: SHIFT_DOWN => {
573
+ self . extend_selection ( ExtendType :: Down ) ?;
574
+ Ok ( true )
575
+ }
576
+ keys:: SHIFT_UP => {
577
+ self . extend_selection ( ExtendType :: Up ) ?;
578
+ Ok ( true )
579
+ }
580
+ keys:: END => {
516
581
self . move_selection ( ScrollType :: End ) ?;
517
582
Ok ( true )
518
583
}
519
- keys:: HOME | keys :: SHIFT_UP => {
584
+ keys:: HOME => {
520
585
self . move_selection ( ScrollType :: Home ) ?;
521
586
Ok ( true )
522
587
}
0 commit comments