Skip to content

Commit 3341ce3

Browse files
committed
feat: Choose full diff based on terminal height
1 parent f1e03e0 commit 3341ce3

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ clap = { version = "4.5.1", features = ["derive", "env", "wrap_help"] }
2121
console = "0.15.8"
2222
dialoguer = "0.11.0"
2323
git2 = { version = "0.18.2", default-features = false }
24+
terminal_size = "0.3.0"
2425
syntect = "5.2.0"
26+
termcolor = "1.4.1"
2527

2628
[dev-dependencies]
2729
assert_cmd = "2.0.13"

src/lib.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashMap;
2+
use std::io::Write as _;
23

34
use anyhow::{anyhow, bail, Context};
45
use console::style;
@@ -11,6 +12,8 @@ use syntect::easy::HighlightLines;
1112
use syntect::highlighting::ThemeSet;
1213
use syntect::parsing::SyntaxSet;
1314
use syntect::util::as_24_bit_terminal_escaped;
15+
use termcolor::{ColorChoice, StandardStream, WriteColor as _};
16+
use terminal_size::{terminal_size, Height};
1417

1518
const DEFAULT_UPSTREAM_BRANCHES: &[&str] = &["main", "master", "develop", "trunk"];
1619

@@ -248,11 +251,18 @@ fn create_diff(repo: &Repository, require_newline: bool) -> Result<Diff, anyhow:
248251
let diff = if diffstat.files_changed() == 0 {
249252
let dirty_workdir_stats = dirty_diff.stats()?;
250253
if dirty_workdir_stats.files_changed() > 0 {
254+
let Height(h) = terminal_size().map(|(_w, h)| h).unwrap_or(Height(24));
255+
let cutoff_height = (h - 5) as usize; // give some room for the prompt
251256
let total_change = dirty_workdir_stats.insertions() + dirty_workdir_stats.deletions();
252-
if total_change < 50 {
253-
native_diff(&dirty_diff)?;
254-
} else {
257+
if total_change >= cutoff_height {
255258
print_diffstat("Unstaged", &dirty_diff)?;
259+
} else {
260+
let diff_lines = native_diff(&dirty_diff)?;
261+
if diff_lines.len() >= cutoff_height {
262+
print_diffstat("Unstaged", &dirty_diff)?;
263+
} else {
264+
print_diff_lines(&diff_lines)?;
265+
}
256266
}
257267
if !Confirm::new()
258268
.with_prompt("Nothing staged, stage and commit everything?")
@@ -419,13 +429,14 @@ fn format_ref(rf: &git2::Reference<'_>) -> Result<String, anyhow::Error> {
419429

420430
// diff helpers
421431

422-
fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
432+
fn native_diff(diff: &Diff<'_>) -> Result<Vec<String>, anyhow::Error> {
423433
let ss = SyntaxSet::load_defaults_newlines();
424434
let ts = ThemeSet::load_defaults();
425435
let syntax = ss.find_syntax_by_extension("patch").unwrap();
426436
let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
427437

428438
let mut inner_err = None;
439+
let mut diff_lines = Vec::new();
429440

430441
diff.print(DiffFormat::Patch, |_delta, _hunk, line| {
431442
let content = std::str::from_utf8(line.content()).unwrap();
@@ -441,7 +452,7 @@ fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
441452
}
442453
};
443454
let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
444-
print!("{}", escaped);
455+
diff_lines.push(escaped);
445456
}
446457
_ => {
447458
let ranges = match h.highlight_line(content, &ss) {
@@ -452,7 +463,7 @@ fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
452463
}
453464
};
454465
let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
455-
print!("{}", escaped);
466+
diff_lines.push(escaped);
456467
}
457468
}
458469
true
@@ -461,10 +472,20 @@ fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
461472
if let Some(err) = inner_err {
462473
Err(err.into())
463474
} else {
464-
Ok(())
475+
Ok(diff_lines)
465476
}
466477
}
467478

479+
fn print_diff_lines(diff_lines: &[String]) -> Result<(), anyhow::Error> {
480+
let mut stdout = StandardStream::stdout(ColorChoice::Auto);
481+
for line in diff_lines {
482+
write!(&mut stdout, "{}", line)?;
483+
}
484+
stdout.reset()?;
485+
writeln!(&mut stdout)?;
486+
Ok(())
487+
}
488+
468489
fn print_diffstat(prefix: &str, diff: &Diff<'_>) -> Result<(), anyhow::Error> {
469490
let buf = diff.stats()?.to_buf(DiffStatsFormat::FULL, 80)?;
470491
let stat = std::str::from_utf8(&buf).context("converting diffstat to utf-8")?;

0 commit comments

Comments
 (0)