gitwig 2.0.3

a rust based tui, an alternative to sourcetree and gitui
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
use crate::app::{App, DetailSection, Mode};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};

pub struct InspectPopup;

impl InspectPopup {
    pub fn handle_event(app: &mut App, key: KeyEvent) -> bool {
        let code = key.code;

        match code {
            KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('Q') => {
                if app.inspect_full_diff {
                    app.inspect_full_diff = false;
                } else if app.in_logs_ui {
                    app.mode = Mode::Logs;
                } else {
                    app.mode = Mode::Detail;
                    app.detail_focus = DetailSection::Commits;
                }
            }
            KeyCode::Char('?') => {
                app.open_detail_help();
            }
            KeyCode::Char('w') | KeyCode::Tab => {
                if app.is_uncommitted_selected() {
                    let mut next_focus = match app.detail_focus {
                        DetailSection::Staged => DetailSection::Unstaged,
                        DetailSection::Unstaged => DetailSection::Conflicts,
                        DetailSection::Conflicts => DetailSection::StagingDetails,
                        DetailSection::StagingDetails => DetailSection::ConflictDiff,
                        _ => DetailSection::Staged,
                    };
                    for _ in 0..6 {
                        let skip = match next_focus {
                            DetailSection::Staged => app.is_staged_empty(),
                            DetailSection::Unstaged => app.is_unstaged_empty(),
                            DetailSection::Conflicts => app.is_conflicted_empty(),
                            DetailSection::StagingDetails => {
                                app.is_staged_empty() && app.is_unstaged_empty()
                            }
                            DetailSection::ConflictDiff => app.is_conflicted_empty(),
                            _ => false,
                        };
                        if skip {
                            next_focus = match next_focus {
                                DetailSection::Staged => DetailSection::Unstaged,
                                DetailSection::Unstaged => DetailSection::Conflicts,
                                DetailSection::Conflicts => DetailSection::StagingDetails,
                                DetailSection::StagingDetails => DetailSection::ConflictDiff,
                                _ => DetailSection::Staged,
                            };
                        } else {
                            break;
                        }
                    }
                    if app.detail_focus == DetailSection::Staged
                        || app.detail_focus == DetailSection::Unstaged
                        || app.detail_focus == DetailSection::Conflicts
                    {
                        app.last_staging_focus = app.detail_focus;
                    }
                    app.detail_focus = next_focus;
                    app.diff.diff_scroll = 0;
                    app.refresh_staging_diff();
                } else {
                    let mut next_focus = match app.detail_focus {
                        DetailSection::Staged => DetailSection::StagingDetails,
                        DetailSection::StagingDetails => DetailSection::CommitDetails,
                        _ => DetailSection::Staged,
                    };
                    for _ in 0..3 {
                        let skip = match next_focus {
                            DetailSection::Staged => app.is_selected_commit_empty(),
                            DetailSection::CommitDetails => false,
                            DetailSection::StagingDetails => app.is_selected_commit_empty(),
                            _ => false,
                        };
                        if skip {
                            next_focus = match next_focus {
                                DetailSection::Staged => DetailSection::CommitDetails,
                                DetailSection::CommitDetails => DetailSection::StagingDetails,
                                _ => DetailSection::Staged,
                            };
                        } else {
                            break;
                        }
                    }
                    app.detail_focus = next_focus;
                }
            }
            KeyCode::Char('W') => {
                if app.is_uncommitted_selected() {
                    let mut next_focus = match app.detail_focus {
                        DetailSection::Staged => DetailSection::ConflictDiff,
                        DetailSection::ConflictDiff => DetailSection::StagingDetails,
                        DetailSection::StagingDetails => DetailSection::Conflicts,
                        DetailSection::Conflicts => DetailSection::Unstaged,
                        _ => DetailSection::Staged,
                    };
                    for _ in 0..6 {
                        let skip = match next_focus {
                            DetailSection::Staged => app.is_staged_empty(),
                            DetailSection::Unstaged => app.is_unstaged_empty(),
                            DetailSection::Conflicts => app.is_conflicted_empty(),
                            DetailSection::StagingDetails => {
                                app.is_staged_empty() && app.is_unstaged_empty()
                            }
                            DetailSection::ConflictDiff => app.is_conflicted_empty(),
                            _ => false,
                        };
                        if skip {
                            next_focus = match next_focus {
                                DetailSection::Staged => DetailSection::ConflictDiff,
                                DetailSection::ConflictDiff => DetailSection::StagingDetails,
                                DetailSection::StagingDetails => DetailSection::Conflicts,
                                DetailSection::Conflicts => DetailSection::Unstaged,
                                _ => DetailSection::Staged,
                            };
                        } else {
                            break;
                        }
                    }
                    if app.detail_focus == DetailSection::Staged
                        || app.detail_focus == DetailSection::Unstaged
                        || app.detail_focus == DetailSection::Conflicts
                    {
                        app.last_staging_focus = app.detail_focus;
                    }
                    app.detail_focus = next_focus;
                    app.diff.diff_scroll = 0;
                    app.refresh_staging_diff();
                } else {
                    let mut next_focus = match app.detail_focus {
                        DetailSection::Staged => DetailSection::CommitDetails,
                        DetailSection::CommitDetails => DetailSection::StagingDetails,
                        _ => DetailSection::Staged,
                    };
                    for _ in 0..3 {
                        let skip = match next_focus {
                            DetailSection::Staged => app.is_selected_commit_empty(),
                            DetailSection::CommitDetails => false,
                            DetailSection::StagingDetails => app.is_selected_commit_empty(),
                            _ => false,
                        };
                        if skip {
                            next_focus = match next_focus {
                                DetailSection::Staged => DetailSection::StagingDetails,
                                DetailSection::StagingDetails => DetailSection::CommitDetails,
                                _ => DetailSection::Staged,
                            };
                        } else {
                            break;
                        }
                    }
                    app.detail_focus = next_focus;
                }
            }
            KeyCode::Right => {
                if app.detail_focus == DetailSection::StagingDetails
                    || app.detail_focus == DetailSection::ConflictDiff
                {
                    app.inspect_full_diff = true;
                } else if app.is_uncommitted_selected() {
                    if app.detail_focus == DetailSection::Staged
                        || app.detail_focus == DetailSection::Unstaged
                        || app.detail_focus == DetailSection::Conflicts
                    {
                        app.last_staging_focus = app.detail_focus;
                        if app.detail_focus == DetailSection::Conflicts {
                            app.detail_focus = DetailSection::ConflictDiff;
                        } else {
                            app.detail_focus = DetailSection::StagingDetails;
                        }
                    }
                } else {
                    if app.detail_focus == DetailSection::Staged
                        || app.detail_focus == DetailSection::CommitDetails
                    {
                        app.detail_focus = DetailSection::StagingDetails;
                    }
                }
            }
            KeyCode::Left => {
                if app.inspect_full_diff {
                    app.inspect_full_diff = false;
                } else if app.detail_focus == DetailSection::StagingDetails
                    || app.detail_focus == DetailSection::ConflictDiff
                {
                    if app.is_uncommitted_selected() {
                        app.detail_focus = app.last_staging_focus;
                    } else {
                        app.detail_focus = DetailSection::CommitDetails;
                    }
                }
            }
            KeyCode::Up | KeyCode::Char('k') | KeyCode::Char('K') => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                    || app.detail_focus == DetailSection::Conflicts
                {
                    if app.detail_focus == DetailSection::Conflicts {
                        app.conflict_file_up();
                    } else if app.is_uncommitted_selected() {
                        app.staging_file_up();
                    } else {
                        app.detail_file_up();
                    }
                } else if app.detail_focus == DetailSection::CommitDetails {
                    app.commit_list.details_scroll_up();
                } else {
                    if app.is_uncommitted_selected() {
                        if app.diff.diff_line_mode {
                            app.diff_line_up();
                        } else {
                            app.diff_hunk_up();
                        }
                    } else {
                        app.diff.diff_scroll_up();
                    }
                }
            }
            KeyCode::Down | KeyCode::Char('j') | KeyCode::Char('J') => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                    || app.detail_focus == DetailSection::Conflicts
                {
                    if app.detail_focus == DetailSection::Conflicts {
                        app.conflict_file_down();
                    } else if app.is_uncommitted_selected() {
                        app.staging_file_down();
                    } else {
                        app.detail_file_down();
                    }
                } else if app.detail_focus == DetailSection::CommitDetails {
                    app.commit_list.details_scroll_down();
                } else {
                    if app.is_uncommitted_selected() {
                        if app.diff.diff_line_mode {
                            app.diff_line_down();
                        } else {
                            app.diff_hunk_down();
                        }
                    } else {
                        app.diff.diff_scroll_down();
                    }
                }
            }
            KeyCode::PageUp => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                    || app.detail_focus == DetailSection::Conflicts
                {
                    if app.detail_focus == DetailSection::Conflicts {
                        for _ in 0..app.config.page_size {
                            app.conflict_file_up();
                        }
                    } else if app.is_uncommitted_selected() {
                        for _ in 0..app.config.page_size {
                            app.staging_file_up();
                        }
                    } else {
                        for _ in 0..app.config.page_size {
                            app.detail_file_up();
                        }
                    }
                } else if app.detail_focus == DetailSection::CommitDetails {
                    for _ in 0..app.config.page_size {
                        app.commit_list.details_scroll_up();
                    }
                } else {
                    app.diff.diff_scroll_page_up(app.config.page_size);
                }
            }
            KeyCode::PageDown => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                    || app.detail_focus == DetailSection::Conflicts
                {
                    if app.detail_focus == DetailSection::Conflicts {
                        for _ in 0..app.config.page_size {
                            app.conflict_file_down();
                        }
                    } else if app.is_uncommitted_selected() {
                        for _ in 0..app.config.page_size {
                            app.staging_file_down();
                        }
                    } else {
                        for _ in 0..app.config.page_size {
                            app.detail_file_down();
                        }
                    }
                } else if app.detail_focus == DetailSection::CommitDetails {
                    for _ in 0..app.config.page_size {
                        app.commit_list.details_scroll_down();
                    }
                } else {
                    app.diff.diff_scroll_page_down(app.config.page_size);
                }
            }
            KeyCode::Home => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                    || app.detail_focus == DetailSection::Conflicts
                {
                    if app.detail_focus == DetailSection::Conflicts {
                        app.status_list.conflict_file_selection = 0;
                        app.refresh_staging_diff();
                    } else if app.is_uncommitted_selected() {
                        app.status_list.staging_file_selection = 0;
                        app.refresh_staging_diff();
                    } else {
                        app.status_list.file_selection = 0;
                        app.refresh_file_diff();
                    }
                } else if app.detail_focus == DetailSection::CommitDetails {
                    app.commit_list.details_scroll = 0;
                } else {
                    if app.is_uncommitted_selected() {
                        if app.diff.diff_line_mode {
                            app.diff.diff_line_selection = 0;
                            app.diff.diff_scroll = 0;
                        } else {
                            app.diff.diff_hunk_selection = 0;
                            app.scroll_to_selected_hunk();
                        }
                    } else {
                        app.diff.diff_scroll_to_top();
                    }
                }
            }
            KeyCode::End => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                    || app.detail_focus == DetailSection::Conflicts
                {
                    if app.detail_focus == DetailSection::Conflicts {
                        let len = match &app.current_detail {
                            Some(crate::repo::ItemDetail::Repo { info, .. }) => {
                                info.changes.conflicted.len()
                            }
                            _ => 0,
                        };
                        app.status_list.conflict_file_selection = len.saturating_sub(1);
                        app.refresh_staging_diff();
                    } else if app.is_uncommitted_selected() {
                        app.status_list.staging_file_selection =
                            app.staging_file_total().saturating_sub(1);
                        app.refresh_staging_diff();
                    } else {
                        app.status_list.file_selection = app.file_total().saturating_sub(1);
                        app.refresh_file_diff();
                    }
                } else if app.detail_focus == DetailSection::CommitDetails {
                    app.commit_list.details_scroll = usize::MAX;
                } else {
                    if app.is_uncommitted_selected() {
                        if app.diff.diff_line_mode {
                            app.diff.diff_line_selection =
                                app.diff.file_diff.len().saturating_sub(1);
                            app.diff.diff_scroll = app.diff.diff_line_selection.saturating_sub(17);
                        } else {
                            let hunk_count = app.get_diff_hunk_ranges().len();
                            app.diff.diff_hunk_selection = hunk_count.saturating_sub(1);
                            app.scroll_to_selected_hunk();
                        }
                    } else {
                        app.diff.diff_scroll_to_bottom();
                    }
                }
            }
            KeyCode::Enter if app.is_uncommitted_selected() => {
                if app.detail_focus == DetailSection::Staged {
                    app.unstage_selected_file();
                } else if app.detail_focus == DetailSection::Unstaged {
                    app.stage_selected_file();
                } else if app.detail_focus == DetailSection::Conflicts {
                    app.detail_focus = DetailSection::ConflictDiff;
                    app.diff.diff_scroll = 0;
                    app.refresh_staging_diff();
                } else if app.detail_focus == DetailSection::StagingDetails {
                    if app.diff.diff_line_mode {
                        if app.last_staging_focus == DetailSection::Staged {
                            app.unstage_selected_line();
                        } else if app.last_staging_focus == DetailSection::Unstaged {
                            app.stage_selected_line();
                        }
                    } else {
                        if app.last_staging_focus == DetailSection::Staged {
                            app.unstage_selected_hunk();
                        } else if app.last_staging_focus == DetailSection::Unstaged {
                            app.stage_selected_hunk();
                        }
                    }
                }
            }
            KeyCode::Delete
                if app.is_uncommitted_selected()
                    && app.detail_focus == DetailSection::StagingDetails
                    && app.last_staging_focus == DetailSection::Unstaged =>
            {
                if app.diff.diff_line_mode {
                    app.discard_selected_line();
                } else {
                    app.discard_selected_hunk();
                }
            }
            KeyCode::Char('x') if app.is_uncommitted_selected() => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                {
                    app.request_discard_changes();
                } else if app.detail_focus == DetailSection::StagingDetails
                    && app.last_staging_focus == DetailSection::Unstaged
                {
                    if app.diff.diff_line_mode {
                        app.discard_selected_line();
                    } else {
                        app.discard_selected_hunk();
                    }
                }
            }
            KeyCode::Char('X') if app.is_uncommitted_selected() => {
                if app.detail_focus == DetailSection::Staged
                    || app.detail_focus == DetailSection::Unstaged
                {
                    app.request_discard_all_changes();
                } else if app.detail_focus == DetailSection::StagingDetails
                    && app.last_staging_focus == DetailSection::Unstaged
                {
                    if app.diff.diff_line_mode {
                        app.discard_selected_line();
                    } else {
                        app.discard_selected_hunk();
                    }
                }
            }
            KeyCode::Char('a') if app.is_uncommitted_selected() => {
                if app.detail_focus == DetailSection::Unstaged {
                    app.stage_all_changes();
                } else if app.detail_focus == DetailSection::Staged {
                    app.unstage_all_changes();
                }
            }
            KeyCode::Char('l') | KeyCode::Char('L')
                if app.is_uncommitted_selected()
                    && app.detail_focus == DetailSection::StagingDetails =>
            {
                app.toggle_diff_line_mode();
            }
            KeyCode::Char('o')
                if (app.detail_focus == DetailSection::Conflicts
                    || app.detail_focus == DetailSection::ConflictDiff)
                    && app.is_uncommitted_selected() =>
            {
                app.resolve_conflict_ours();
            }
            KeyCode::Char('t')
                if (app.detail_focus == DetailSection::Conflicts
                    || app.detail_focus == DetailSection::ConflictDiff)
                    && app.is_uncommitted_selected() =>
            {
                app.resolve_conflict_theirs();
            }
            KeyCode::Char('r')
                if (app.detail_focus == DetailSection::Conflicts
                    || app.detail_focus == DetailSection::ConflictDiff)
                    && app.is_uncommitted_selected() =>
            {
                app.mark_conflict_resolved();
            }
            KeyCode::Char('A')
                if (app.detail_focus == DetailSection::Conflicts
                    || app.detail_focus == DetailSection::ConflictDiff)
                    && app.is_uncommitted_selected() =>
            {
                app.mode = Mode::MergeAbortConfirm;
            }
            KeyCode::Char('C')
                if (app.detail_focus == DetailSection::Conflicts
                    || app.detail_focus == DetailSection::ConflictDiff)
                    && app.is_uncommitted_selected() =>
            {
                app.mode = Mode::MergeContinueConfirm;
            }
            KeyCode::Char('c') if app.is_uncommitted_selected() => {
                app.start_commit();
            }
            KeyCode::Char('C') if app.is_uncommitted_selected() => {
                app.start_commit_amend();
            }
            _ => {}
        }
        false
    }
}