1
1
use std:: collections:: HashMap ;
2
+ use std:: io:: Write as _;
2
3
3
4
use anyhow:: { anyhow, bail, Context } ;
4
5
use console:: style;
@@ -11,6 +12,8 @@ use syntect::easy::HighlightLines;
11
12
use syntect:: highlighting:: ThemeSet ;
12
13
use syntect:: parsing:: SyntaxSet ;
13
14
use syntect:: util:: as_24_bit_terminal_escaped;
15
+ use termcolor:: { ColorChoice , StandardStream , WriteColor as _} ;
16
+ use terminal_size:: { terminal_size, Height } ;
14
17
15
18
const DEFAULT_UPSTREAM_BRANCHES : & [ & str ] = & [ "main" , "master" , "develop" , "trunk" ] ;
16
19
@@ -248,11 +251,18 @@ fn create_diff(repo: &Repository, require_newline: bool) -> Result<Diff, anyhow:
248
251
let diff = if diffstat. files_changed ( ) == 0 {
249
252
let dirty_workdir_stats = dirty_diff. stats ( ) ?;
250
253
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
251
256
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 {
255
258
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
+ }
256
266
}
257
267
if !Confirm :: new ( )
258
268
. with_prompt ( "Nothing staged, stage and commit everything?" )
@@ -419,13 +429,14 @@ fn format_ref(rf: &git2::Reference<'_>) -> Result<String, anyhow::Error> {
419
429
420
430
// diff helpers
421
431
422
- fn native_diff ( diff : & Diff < ' _ > ) -> Result < ( ) , anyhow:: Error > {
432
+ fn native_diff ( diff : & Diff < ' _ > ) -> Result < Vec < String > , anyhow:: Error > {
423
433
let ss = SyntaxSet :: load_defaults_newlines ( ) ;
424
434
let ts = ThemeSet :: load_defaults ( ) ;
425
435
let syntax = ss. find_syntax_by_extension ( "patch" ) . unwrap ( ) ;
426
436
let mut h = HighlightLines :: new ( syntax, & ts. themes [ "base16-ocean.dark" ] ) ;
427
437
428
438
let mut inner_err = None ;
439
+ let mut diff_lines = Vec :: new ( ) ;
429
440
430
441
diff. print ( DiffFormat :: Patch , |_delta, _hunk, line| {
431
442
let content = std:: str:: from_utf8 ( line. content ( ) ) . unwrap ( ) ;
@@ -441,7 +452,7 @@ fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
441
452
}
442
453
} ;
443
454
let escaped = as_24_bit_terminal_escaped ( & ranges[ ..] , true ) ;
444
- print ! ( "{}" , escaped) ;
455
+ diff_lines . push ( escaped) ;
445
456
}
446
457
_ => {
447
458
let ranges = match h. highlight_line ( content, & ss) {
@@ -452,7 +463,7 @@ fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
452
463
}
453
464
} ;
454
465
let escaped = as_24_bit_terminal_escaped ( & ranges[ ..] , true ) ;
455
- print ! ( "{}" , escaped) ;
466
+ diff_lines . push ( escaped) ;
456
467
}
457
468
}
458
469
true
@@ -461,10 +472,20 @@ fn native_diff(diff: &Diff<'_>) -> Result<(), anyhow::Error> {
461
472
if let Some ( err) = inner_err {
462
473
Err ( err. into ( ) )
463
474
} else {
464
- Ok ( ( ) )
475
+ Ok ( diff_lines )
465
476
}
466
477
}
467
478
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
+
468
489
fn print_diffstat ( prefix : & str , diff : & Diff < ' _ > ) -> Result < ( ) , anyhow:: Error > {
469
490
let buf = diff. stats ( ) ?. to_buf ( DiffStatsFormat :: FULL , 80 ) ?;
470
491
let stat = std:: str:: from_utf8 ( & buf) . context ( "converting diffstat to utf-8" ) ?;
0 commit comments