@@ -127,7 +127,7 @@ fn chrono_like_now() -> impl std::fmt::Display {
127127 let z = s. div_euclid ( SECS_PER_DAY ) ;
128128 let secs_of_day = s. rem_euclid ( SECS_PER_DAY ) ;
129129 let a = z + 719468 ;
130- let era = ( a >= 0 ) . then_some ( a ) . unwrap_or ( a - 146096 ) / 146097 ;
130+ let era = ( if a >= 0 { a } else { a - 146096 } ) ;
131131 let doe = a - era * 146097 ;
132132 let yoe = ( doe - doe/1460 + doe/36524 - doe/146096 ) / 365 ;
133133 let y = ( yoe as i32 ) + era as i32 * 400 ;
@@ -154,7 +154,7 @@ fn main() -> Result<()> {
154154 // Enumerate ports up front
155155 let all_ports = serialport:: available_ports ( )
156156 . context ( "Failed to list serial ports" ) ?;
157-
157+
158158 // Filter for realistic ports (USB ports with VID/PID)
159159 let ports: Vec < _ > = all_ports. into_iter ( )
160160 . filter ( |p| matches ! ( & p. port_type, SerialPortType :: UsbPort ( _) ) )
@@ -243,18 +243,17 @@ fn main() -> Result<()> {
243243 let shutdown_tx = shutdown_tx. clone ( ) ;
244244 ctrlc:: set_handler ( move || {
245245 running. store ( false , Ordering :: SeqCst ) ;
246- if let Ok ( tx_guard) = shutdown_tx. lock ( ) {
247- if let Some ( tx) = tx_guard. as_ref ( ) {
246+ if let Ok ( tx_guard) = shutdown_tx. lock ( )
247+ && let Some ( tx) = tx_guard. as_ref ( ) {
248248 let _ = tx. send ( UiMessage :: Quit ) ;
249249 }
250- }
251250 } ) . expect ( "Failed to set Ctrl-C handler" ) ;
252251 }
253252
254253 // Communication channels for UI
255254 let ( ui_tx, ui_rx) = mpsc:: channel :: < UiMessage > ( ) ;
256255 let ( serial_tx, serial_rx) = mpsc:: channel :: < SerialData > ( ) ;
257-
256+
258257 // Store UI sender for Ctrl-C handler
259258 * shutdown_tx. lock ( ) . unwrap ( ) = Some ( ui_tx. clone ( ) ) ;
260259
@@ -283,7 +282,7 @@ fn main() -> Result<()> {
283282
284283 if n > 0 {
285284 let bytes = & buf[ ..n] ;
286-
285+
287286 // Format the data
288287 let display_text = if hex_mode {
289288 let mut hex_str = String :: new ( ) ;
@@ -307,8 +306,8 @@ fn main() -> Result<()> {
307306 let _ = serial_tx_clone. send ( SerialData :: Received ( display_text) ) ;
308307
309308 // RX log file
310- if let Some ( w) = & rx_log_writer_reader {
311- if let Ok ( mut lw) = w. lock ( ) {
309+ if let Some ( w) = & rx_log_writer_reader
310+ && let Ok ( mut lw) = w. lock ( ) {
312311 if log_ts {
313312 let _ = write ! ( lw, "[{}] " , now_rfc3339( ) ) ;
314313 }
@@ -322,7 +321,6 @@ fn main() -> Result<()> {
322321 }
323322 let _ = lw. flush ( ) ;
324323 }
325- }
326324 }
327325 }
328326 } ) ;
@@ -333,7 +331,7 @@ fn main() -> Result<()> {
333331 crossterm:: execute!( stdout, terminal:: EnterAlternateScreen ) ?;
334332 let backend = CrosstermBackend :: new ( stdout) ;
335333 let mut terminal = Terminal :: new ( backend) ?;
336-
334+
337335 let ui_res = run_ui (
338336 & mut terminal,
339337 ui_rx,
@@ -344,7 +342,7 @@ fn main() -> Result<()> {
344342 tx_log_writer. clone ( ) ,
345343 args. log_ts ,
346344 ) ;
347-
345+
348346 // Cleanup terminal
349347 terminal:: disable_raw_mode ( ) ?;
350348 crossterm:: execute!( terminal. backend_mut( ) , terminal:: LeaveAlternateScreen ) ?;
@@ -449,62 +447,62 @@ impl AppState {
449447 auto_scroll : true ,
450448 }
451449 }
452-
450+
453451 fn add_output ( & mut self , data : String ) {
454452 // Split multi-line data into individual lines for proper scrolling
455453 for line in data. lines ( ) {
456454 self . output_lines . push ( line. to_string ( ) ) ;
457455 }
458-
456+
459457 // If the data didn't end with a newline, the last "line" might be incomplete
460458 // But for serial output, we'll treat each chunk as complete
461-
459+
462460 // Keep only the last 1000 lines to prevent memory issues
463461 if self . output_lines . len ( ) > 1000 {
464462 self . output_lines . drain ( ..self . output_lines . len ( ) - 1000 ) ;
465463 }
466-
464+
467465 // Update auto-scroll state to point to the new bottom (temporary: with highlight to test)
468466 if !self . output_lines . is_empty ( ) {
469467 self . auto_scroll_state . select ( Some ( self . output_lines . len ( ) - 1 ) ) ;
470468 }
471469 }
472-
470+
473471 fn scroll_up ( & mut self ) {
474472 if self . output_lines . is_empty ( ) { return ; }
475473 // Disable auto-scroll when manually scrolling
476474 self . auto_scroll = false ;
477-
475+
478476 let selected = self . list_state . selected ( ) . unwrap_or ( self . output_lines . len ( ) - 1 ) ;
479477 if selected > 0 {
480478 self . list_state . select ( Some ( selected - 1 ) ) ;
481479 }
482480 }
483-
481+
484482 fn scroll_down ( & mut self ) {
485483 if self . output_lines . is_empty ( ) { return ; }
486484 // Disable auto-scroll when manually scrolling
487485 self . auto_scroll = false ;
488-
486+
489487 let selected = self . list_state . selected ( ) . unwrap_or ( 0 ) ;
490488 if selected < self . output_lines . len ( ) - 1 {
491489 self . list_state . select ( Some ( selected + 1 ) ) ;
492490 }
493491 }
494-
492+
495493 fn scroll_to_bottom ( & mut self ) {
496494 if !self . output_lines . is_empty ( ) {
497495 // Disable auto-scroll when manually scrolling to bottom
498496 self . auto_scroll = false ;
499497 self . list_state . select ( Some ( self . output_lines . len ( ) - 1 ) ) ;
500498 }
501499 }
502-
500+
503501 fn enable_auto_scroll ( & mut self ) {
504502 self . auto_scroll = true ;
505503 self . list_state . select ( None ) ; // Clear selection when re-enabling auto-scroll
506504 }
507-
505+
508506 fn scroll_to_home ( & mut self ) {
509507 if !self . output_lines . is_empty ( ) {
510508 // Disable auto-scroll when manually scrolling to top
@@ -569,28 +567,26 @@ fn run_ui<B: Backend>(
569567 // Send the complete line to serial port
570568 if !app_state. input_line . is_empty ( ) {
571569 write_bytes ( & port, app_state. input_line . as_bytes ( ) ) ?;
572- if let Some ( w) = & tx_log {
573- if let Ok ( mut lw) = w. lock ( ) {
570+ if let Some ( w) = & tx_log
571+ && let Ok ( mut lw) = w. lock ( ) {
574572 if log_ts { let _ = write ! ( lw, "[{}] " , now_rfc3339( ) ) ; }
575573 let _ = lw. write_all ( app_state. input_line . as_bytes ( ) ) ;
576574 let _ = lw. flush ( ) ;
577575 }
578- }
579576 }
580-
577+
581578 // Send line ending
582579 let end = line_ending. bytes ( ) ;
583580 if !end. is_empty ( ) {
584581 write_bytes ( & port, end) ?;
585- if let Some ( w) = & tx_log {
586- if let Ok ( mut lw) = w. lock ( ) {
582+ if let Some ( w) = & tx_log
583+ && let Ok ( mut lw) = w. lock ( ) {
587584 if log_ts && app_state. input_line . is_empty ( ) { let _ = write ! ( lw, "[{}] " , now_rfc3339( ) ) ; }
588585 let _ = lw. write_all ( end) ;
589586 let _ = lw. flush ( ) ;
590587 }
591- }
592588 }
593-
589+
594590 // Clear input for next line
595591 app_state. input_line . clear ( ) ;
596592 }
@@ -637,7 +633,7 @@ fn run_ui<B: Backend>(
637633 // Render the UI
638634 terminal. draw ( |f| draw_ui ( f, & mut app_state) ) ?;
639635 }
640-
636+
641637 running. store ( false , Ordering :: SeqCst ) ;
642638 Ok ( ( ) )
643639}
@@ -657,13 +653,13 @@ fn draw_ui(f: &mut Frame, app_state: &mut AppState) {
657653 . iter ( )
658654 . map ( |line| ListItem :: new ( line. as_str ( ) ) )
659655 . collect ( ) ;
660-
656+
661657 let title = if app_state. auto_scroll {
662658 "Serial Monitor (Auto-scroll ON - ↑↓/PgUp/PgDn to scroll, Ctrl+A to re-enable auto-scroll)"
663659 } else {
664660 "Serial Monitor (Auto-scroll OFF - ↑↓/PgUp/PgDn to scroll, Ctrl+A to re-enable auto-scroll)"
665661 } ;
666-
662+
667663 let output_list = List :: new ( output_items)
668664 . block (
669665 Block :: default ( )
@@ -672,16 +668,16 @@ fn draw_ui(f: &mut Frame, app_state: &mut AppState) {
672668 )
673669 . style ( Style :: default ( ) . fg ( Color :: White ) )
674670 . highlight_style ( Style :: default ( ) . fg ( Color :: Black ) . bg ( Color :: White ) ) ;
675-
671+
676672 // Handle auto-scrolling vs manual scrolling
677673 if app_state. auto_scroll {
678674 // Use the persistent auto-scroll state that stays positioned at bottom
679675 f. render_stateful_widget ( output_list, chunks[ 0 ] , & mut app_state. auto_scroll_state ) ;
680676 } else {
681- // Manual scrolling mode - use the user's scroll position
677+ // Manual scrolling mode - use the user's scroll position
682678 f. render_stateful_widget ( output_list, chunks[ 0 ] , & mut app_state. list_state ) ;
683679 }
684-
680+
685681 // Input line
686682 let input_paragraph = Paragraph :: new ( app_state. input_line . as_str ( ) )
687683 . block (
@@ -690,9 +686,9 @@ fn draw_ui(f: &mut Frame, app_state: &mut AppState) {
690686 . title ( "Input (Press Enter to send, Ctrl+C or Esc to exit)" )
691687 )
692688 . style ( Style :: default ( ) . fg ( Color :: Yellow ) ) ;
693-
689+
694690 f. render_widget ( input_paragraph, chunks[ 1 ] ) ;
695-
691+
696692 // Set cursor position in input field
697693 f. set_cursor_position ( (
698694 chunks[ 1 ] . x + app_state. input_line . len ( ) as u16 + 1 ,
0 commit comments