ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: draw bar in progress report

This commit is contained in:
Benjamin Saunders 2022-10-23 13:50:03 -07:00
parent 3dd2cbf799
commit e773709e31
4 changed files with 267 additions and 9 deletions

207
Cargo.lock generated
View file

@ -424,6 +424,31 @@ dependencies = [
"once_cell",
]
[[package]]
name = "crossterm"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
dependencies = [
"bitflags",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
dependencies = [
"winapi",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -692,6 +717,7 @@ dependencies = [
"config",
"criterion",
"criterion_bencher_compat",
"crossterm",
"dirs",
"git2",
"hex",
@ -804,6 +830,16 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.17"
@ -846,6 +882,18 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "mio"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.36.1",
]
[[package]]
name = "nom"
version = "7.1.1"
@ -938,6 +986,29 @@ version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys 0.42.0",
]
[[package]]
name = "pathdiff"
version = "0.2.1"
@ -1333,12 +1404,48 @@ dependencies = [
"digest",
]
[[package]]
name = "signal-hook"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "similar"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803"
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "smawk"
version = "0.3.1"
@ -1725,6 +1832,106 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "yaml-rust"
version = "0.4.5"

View file

@ -40,6 +40,7 @@ clap = { version = "4.0.18", features = ["derive", "deprecated"] }
clap_complete = "4.0.3"
clap_mangen = "0.2.3"
config = { version = "0.13.2", default-features = false, features = ["toml"] }
crossterm = { version = "0.25", default-features = false }
dirs = "4.0.0"
git2 = "0.15.0"
hex = "0.4.3"

View file

@ -1,5 +1,6 @@
use std::time::{Duration, Instant};
use crossterm::terminal::{Clear, ClearType};
use jujutsu_lib::git;
use crate::ui::Ui;
@ -36,19 +37,25 @@ impl<'a> Progress<'a> {
self.printed = true;
self.next_print = now.min(self.next_print + Duration::from_secs(1) / UPDATE_HZ);
const CLEAR_TRAILING: &str = "\x1b[K";
self.buffer.clear();
write!(
self.buffer,
"\r{}{: >3.0}%",
CLEAR_TRAILING,
100.0 * progress.overall
)
.unwrap();
write!(self.buffer, "\r{}", Clear(ClearType::CurrentLine)).unwrap();
let control_chars = self.buffer.len();
write!(self.buffer, "{: >3.0}% ", 100.0 * progress.overall).unwrap();
if let Some(estimate) = rate {
let (scaled, prefix) = binary_prefix(estimate);
write!(self.buffer, " at {: >5.1} {}B/s", scaled, prefix).unwrap();
write!(self.buffer, " at {: >5.1} {}B/s ", scaled, prefix).unwrap();
}
let bar_width = self
.ui
.size()
.map(|(cols, _rows)| usize::from(cols))
.unwrap_or(0)
.saturating_sub(self.buffer.len() - control_chars + 2);
self.buffer.push('[');
draw_progress(progress.overall, &mut self.buffer, bar_width);
self.buffer.push(']');
_ = write!(self.ui, "{}", self.buffer);
_ = self.ui.flush();
}
@ -62,6 +69,23 @@ impl Drop for Progress<'_> {
}
}
fn draw_progress(progress: f32, buffer: &mut String, width: usize) {
const CHARS: [char; 9] = [' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█'];
const RESOLUTION: usize = CHARS.len() - 1;
let ticks = (width as f32 * progress.min(1.0).max(0.0) * RESOLUTION as f32).round() as usize;
let whole = ticks / RESOLUTION;
for _ in 0..whole {
buffer.push(CHARS[CHARS.len() - 1]);
}
if whole < width {
let fraction = ticks % RESOLUTION;
buffer.push(CHARS[fraction]);
}
for _ in (whole + 1)..width {
buffer.push(CHARS[0]);
}
}
const UPDATE_HZ: u32 = 30;
const INITIAL_DELAY: Duration = Duration::from_millis(250);
@ -129,3 +153,25 @@ impl RateEstimateState {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bar() {
let mut buf = String::new();
draw_progress(0.0, &mut buf, 10);
assert_eq!(buf, " ");
buf.clear();
draw_progress(1.0, &mut buf, 10);
assert_eq!(buf, "██████████");
buf.clear();
draw_progress(0.5, &mut buf, 10);
assert_eq!(buf, "█████ ");
buf.clear();
draw_progress(0.54, &mut buf, 10);
assert_eq!(buf, "█████▍ ");
buf.clear();
}
}

View file

@ -176,6 +176,10 @@ impl Ui {
UiOutputPair::Terminal { stdout, .. } => stdout.flush(),
}
}
pub fn size(&self) -> Option<(u16, u16)> {
crossterm::terminal::size().ok()
}
}
enum UiOutputPair {