supporting marking commits in the log

This commit is contained in:
Stephan Dilly 2021-08-17 14:21:24 +02:00
parent a4bdfd16c1
commit 25a49e22f2
4 changed files with 57 additions and 2 deletions

View file

@ -7,6 +7,9 @@ ARGS=-l
profile:
cargo run --features=timing,pprof -- ${ARGS}
run-timing:
cargo run --features=timing --release -- ${ARGS}
debug:
RUST_BACKTRACE=true cargo run --features=timing -- ${ARGS}

View file

@ -10,7 +10,7 @@ use crate::{
ui::style::{SharedTheme, Theme},
};
use anyhow::Result;
use asyncgit::sync::Tags;
use asyncgit::sync::{CommitId, Tags};
use chrono::{DateTime, Local};
use crossterm::event::Event;
use std::{
@ -33,6 +33,7 @@ pub struct CommitList {
branch: Option<String>,
count_total: usize,
items: ItemBatch,
marked: Vec<CommitId>,
scroll_state: (Instant, f32),
tags: Option<Tags>,
current_size: Cell<(u16, u16)>,
@ -50,6 +51,7 @@ impl CommitList {
) -> Self {
Self {
items: ItemBatch::default(),
marked: Vec::with_capacity(2),
selection: 0,
branch: None,
count_total: 0,
@ -164,6 +166,17 @@ impl CommitList {
Ok(needs_update)
}
fn mark(&mut self) {
if let Some(e) = self.selected_entry() {
let id = e.id;
if self.is_marked(&id).unwrap_or_default() {
self.marked.retain(|marked| marked != &id);
} else {
self.marked.push(id);
}
}
}
fn update_scroll_speed(&mut self) {
const REPEATED_SCROLL_THRESHOLD_MILLIS: u128 = 300;
const SCROLL_SPEED_START: f32 = 0.1_f32;
@ -188,6 +201,15 @@ impl CommitList {
self.scroll_state.1 = speed.min(SCROLL_SPEED_MAX);
}
fn is_marked(&self, id: &CommitId) -> Option<bool> {
if self.marked.is_empty() {
None
} else {
let found = self.marked.iter().any(|entry| entry == id);
Some(found)
}
}
fn get_entry_to_add<'a>(
e: &'a LogEntry,
selected: bool,
@ -195,14 +217,26 @@ impl CommitList {
theme: &Theme,
width: usize,
now: DateTime<Local>,
marked: Option<bool>,
) -> Spans<'a> {
let mut txt: Vec<Span> = Vec::new();
txt.reserve(ELEMENTS_PER_LINE);
txt.reserve(
ELEMENTS_PER_LINE + if marked.is_some() { 2 } else { 0 },
);
let splitter_txt = Cow::from(" ");
let splitter =
Span::styled(splitter_txt, theme.text(true, selected));
// marked
if let Some(marked) = marked {
txt.push(Span::styled(
Cow::from(if marked { "X" } else { " " }),
theme.text(true, selected),
));
txt.push(splitter.clone());
}
// commit hash
txt.push(Span::styled(
Cow::from(e.hash_short.as_str()),
@ -258,6 +292,8 @@ impl CommitList {
let now = Local::now();
let any_marked = !self.marked.is_empty();
for (idx, e) in self
.items
.iter()
@ -270,6 +306,13 @@ impl CommitList {
.as_ref()
.and_then(|t| t.get(&e.id))
.map(|tags| tags.join(" "));
let marked = if any_marked {
self.is_marked(&e.id)
} else {
None
};
txt.push(Self::get_entry_to_add(
e,
idx + self.scroll_top.get() == selection,
@ -277,6 +320,7 @@ impl CommitList {
&self.theme,
width,
now,
marked,
));
}
@ -368,6 +412,9 @@ impl Component for CommitList {
self.move_selection(ScrollType::PageUp)?
} else if k == self.key_config.page_down {
self.move_selection(ScrollType::PageDown)?
} else if k == self.key_config.log_mark_commit {
self.mark();
true
} else {
false
};

View file

@ -67,6 +67,7 @@ pub struct KeyConfig {
pub stash_drop: KeyEvent,
pub cmd_bar_toggle: KeyEvent,
pub log_tag_commit: KeyEvent,
pub log_mark_commit: KeyEvent,
pub commit_amend: KeyEvent,
pub copy: KeyEvent,
pub create_branch: KeyEvent,
@ -135,6 +136,7 @@ impl Default for KeyConfig {
stash_drop: KeyEvent { code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT},
cmd_bar_toggle: KeyEvent { code: KeyCode::Char('.'), modifiers: KeyModifiers::empty()},
log_tag_commit: KeyEvent { code: KeyCode::Char('t'), modifiers: KeyModifiers::empty()},
log_mark_commit: KeyEvent { code: KeyCode::Char(' '), modifiers: KeyModifiers::empty()},
commit_amend: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::CONTROL},
copy: KeyEvent { code: KeyCode::Char('y'), modifiers: KeyModifiers::empty()},
create_branch: KeyEvent { code: KeyCode::Char('c'), modifiers: KeyModifiers::empty()},

View file

@ -72,7 +72,10 @@
stash_drop: ( code: Char('D'), modifiers: ( bits: 1,),),
cmd_bar_toggle: ( code: Char('.'), modifiers: ( bits: 0,),),
log_tag_commit: ( code: Char('t'), modifiers: ( bits: 0,),),
log_mark_commit: ( code: Char(' '), modifiers: ( bits: 0,),),
commit_amend: ( code: Char('a'), modifiers: ( bits: 2,),),
copy: ( code: Char('y'), modifiers: ( bits: 0,),),
create_branch: ( code: Char('c'), modifiers: ( bits: 0,),),