@@ -4,7 +4,10 @@ use crate::quotes::Quote;
44use crate :: quotes:: QuotesFile ;
55use console:: { Color , Style } ;
66use rand:: prelude:: * ;
7- use std:: fs;
7+ use std:: sync:: Arc ;
8+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
9+ use std:: time:: Duration ;
10+ use std:: { thread, fs, io:: { self , Write } } ;
811use term_size;
912use textwrap:: wrap;
1013use unicode_width:: UnicodeWidthStr ;
@@ -350,6 +353,12 @@ fn print_boxed(
350353 }
351354}
352355
356+ fn clear_screen ( ) {
357+ // ANSI escape: clear entire screen and move cursor to top-left
358+ print ! ( "\x1B [2J\x1B [H" ) ;
359+ let _ = io:: stdout ( ) . flush ( ) ;
360+ }
361+
353362pub fn render ( runtime : & RuntimeConfig , cli : & crate :: cli:: Cli ) {
354363 // seed
355364 let seed = if cli. seed . unwrap_or ( 0 ) == 0 {
@@ -443,21 +452,112 @@ pub fn render(runtime: &RuntimeConfig, cli: &crate::cli::Cli) {
443452
444453 let border_color = color_from_hex ( & runtime. border_color ) ;
445454
446- print_boxed (
447- jap_lines,
448- jap_style,
449- runtime. horizontal_padding ,
450- runtime. vertical_padding ,
451- runtime. width ,
452- runtime. border ,
453- runtime. rounded_border ,
454- border_color,
455- translation,
456- show_translation,
457- translation_style,
458- quote. source . as_deref ( ) ,
459- show_source,
460- source_style,
461- runtime. centered ,
462- ) ;
455+ if runtime. dynamic {
456+ // Dynamic recentering mode
457+ let running = Arc :: new ( AtomicBool :: new ( true ) ) ;
458+ let r = running. clone ( ) ;
459+
460+ // Handle Ctrl+C gracefully
461+ ctrlc:: set_handler ( move || {
462+ r. store ( false , Ordering :: SeqCst ) ;
463+ } ) . expect ( "Error setting Ctrl-C handler" ) ;
464+
465+ // Hide cursor
466+ print ! ( "\x1B [?25l" ) ;
467+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
468+
469+ let mut last_size = term_size:: dimensions ( ) ;
470+
471+ while running. load ( Ordering :: SeqCst ) {
472+ clear_screen ( ) ;
473+
474+ let ( _, term_h) = term_size:: dimensions ( ) . unwrap_or ( ( 80 , 24 ) ) ;
475+
476+ let mut vertical = 0 ;
477+ let mut horizontal = 0 ;
478+
479+ if runtime. border {
480+ vertical = runtime. vertical_padding ;
481+ horizontal = runtime. horizontal_padding ;
482+ }
483+
484+ // estimate how many lines the box will take (content + borders + padding)
485+ let content_lines = {
486+ let mut count = jap_lines. len ( ) ;
487+ if show_translation { count += 1 ; }
488+ if show_source { count += 1 ; }
489+ // Add vertical padding and border lines
490+ count += vertical * 2 ;
491+ if runtime. border { count += 2 ; }
492+ count
493+ } ;
494+
495+ // Compute top blank lines to center vertically
496+ let top_blank = if term_h > content_lines {
497+ ( term_h - content_lines) / 2
498+ } else {
499+ 1
500+ } ;
501+
502+ // Print top spacing
503+ for _ in 0 ..top_blank {
504+ println ! ( ) ;
505+ }
506+
507+ // Render centered block
508+ print_boxed (
509+ jap_lines. clone ( ) ,
510+ jap_style. clone ( ) ,
511+ horizontal,
512+ vertical,
513+ runtime. width ,
514+ runtime. border ,
515+ runtime. rounded_border ,
516+ border_color. clone ( ) ,
517+ translation,
518+ show_translation,
519+ translation_style. clone ( ) ,
520+ quote. source . as_deref ( ) ,
521+ show_source,
522+ source_style. clone ( ) ,
523+ runtime. centered ,
524+ ) ;
525+
526+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
527+
528+ // Sleep before checking for resize or exit
529+ thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
530+
531+ let current_size = term_size:: dimensions ( ) ;
532+ if current_size != last_size {
533+ last_size = current_size;
534+ clear_screen ( ) ; // redraw on resize
535+ }
536+ }
537+
538+ // Show cursor again before exiting
539+ print ! ( "\x1B [?25h" ) ;
540+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
541+
542+ clear_screen ( ) ; // clean terminal on exit
543+ } else {
544+ // Normal static render
545+ print_boxed (
546+ jap_lines,
547+ jap_style,
548+ runtime. horizontal_padding ,
549+ runtime. vertical_padding ,
550+ runtime. width ,
551+ runtime. border ,
552+ runtime. rounded_border ,
553+ border_color,
554+ translation,
555+ show_translation,
556+ translation_style,
557+ quote. source . as_deref ( ) ,
558+ show_source,
559+ source_style,
560+ runtime. centered ,
561+ ) ;
562+ }
463563}
0 commit comments