@@ -371,38 +371,38 @@ pub fn render_enumerate_table(rows: &[EnumRow]) -> String {
371371
372372 // Fixed columns: Handles, Service > Characteristics, Properties
373373 // These size to content. Data and ASCII get the remaining space.
374- let headers = [ "Handles" , "Service > Characteristics" , "Properties" , "Data " , "ASCII " ] ;
374+ let headers = [ "Handles" , "Service > Characteristics" , "Properties" , "ASCII " , "Data " ] ;
375375 let ncols = 5 ;
376376
377377 // Measure fixed column widths from content
378378 let mut w_handles = headers[ 0 ] . len ( ) ;
379379 let mut w_desc = headers[ 1 ] . len ( ) ;
380380 let mut w_props = headers[ 2 ] . len ( ) ;
381- let mut max_data = headers[ 3 ] . len ( ) ;
382- let mut max_ascii = headers[ 4 ] . len ( ) ;
381+ let mut max_ascii = headers[ 3 ] . len ( ) ;
382+ let mut max_data = headers[ 4 ] . len ( ) ;
383383
384384 for row in rows {
385385 w_handles = w_handles. max ( visible_len ( & row. handles ) ) ;
386386 w_desc = w_desc. max ( visible_len ( & row. description ) ) ;
387387 w_props = w_props. max ( visible_len ( & row. properties ) ) ;
388- max_data = max_data. max ( row. data . len ( ) ) ;
389388 max_ascii = max_ascii. max ( row. ascii . len ( ) ) ;
389+ max_data = max_data. max ( row. data . len ( ) ) ;
390390 }
391391
392392 // Calculate overhead: ncols borders + padding (2 per col) + 1 trailing border
393393 // "│ col │ col │ col │ col │ col │"
394394 let overhead = ncols + 1 + ncols * 2 ; // 6 borders + 10 padding = 16
395395 let fixed_used = w_handles + w_desc + w_props + overhead;
396396
397- // Remaining space for data + ascii
397+ // Remaining space for ascii + data
398398 let remaining = tw. saturating_sub ( fixed_used) ;
399399
400400 // Split remaining: give ASCII ~1/4 (it's compact), Data ~3/4
401401 // But never less than header width, and never more than content needs
402- let w_ascii = max_ascii. min ( remaining / 4 ) . max ( headers[ 4 ] . len ( ) ) . max ( 5 ) ;
403- let w_data = remaining. saturating_sub ( w_ascii) . max ( headers[ 3 ] . len ( ) ) . max ( 8 ) ;
402+ let w_ascii = max_ascii. min ( remaining / 4 ) . max ( headers[ 3 ] . len ( ) ) . max ( 5 ) ;
403+ let w_data = remaining. saturating_sub ( w_ascii) . max ( headers[ 4 ] . len ( ) ) . max ( 8 ) ;
404404
405- let widths = [ w_handles, w_desc, w_props, w_data , w_ascii ] ;
405+ let widths = [ w_handles, w_desc, w_props, w_ascii , w_data ] ;
406406
407407 let mut out = String :: new ( ) ;
408408 let b = ctp ( "─" , SURFACE1 ) ;
@@ -463,9 +463,9 @@ pub fn render_enumerate_table(rows: &[EnumRow]) -> String {
463463
464464 let c_props = colorize_props ( & row. properties ) ;
465465
466- // Wrap data and ascii into lines that fit their column widths
467- let data_lines = wrap_plain_text ( & row. data , w_data) ;
466+ // Wrap ascii and data into lines that fit their column widths
468467 let ascii_lines = wrap_plain_text ( & row. ascii , w_ascii) ;
468+ let data_lines = wrap_plain_text ( & row. data , w_data) ;
469469 let num_lines = data_lines. len ( ) . max ( ascii_lines. len ( ) ) . max ( 1 ) ;
470470
471471 for line_idx in 0 ..num_lines {
@@ -507,20 +507,6 @@ pub fn render_enumerate_table(rows: &[EnumRow]) -> String {
507507 out. push ( ' ' ) ;
508508 out. push_str ( & v. to_string ( ) ) ;
509509
510- // Data
511- out. push ( ' ' ) ;
512- let data_chunk = data_lines. get ( line_idx) . map ( |s| s. as_str ( ) ) . unwrap_or ( "" ) ;
513- let c_data = if !data_chunk. is_empty ( ) {
514- ctp ( data_chunk, FLAMINGO ) . to_string ( )
515- } else {
516- String :: new ( )
517- } ;
518- let data_vlen = visible_len ( & c_data) ;
519- out. push_str ( & c_data) ;
520- out. push_str ( & " " . repeat ( w_data. saturating_sub ( data_vlen) ) ) ;
521- out. push ( ' ' ) ;
522- out. push_str ( & v. to_string ( ) ) ;
523-
524510 // ASCII
525511 out. push ( ' ' ) ;
526512 let ascii_chunk = ascii_lines. get ( line_idx) . map ( |s| s. as_str ( ) ) . unwrap_or ( "" ) ;
@@ -535,6 +521,20 @@ pub fn render_enumerate_table(rows: &[EnumRow]) -> String {
535521 out. push ( ' ' ) ;
536522 out. push_str ( & v. to_string ( ) ) ;
537523
524+ // Data
525+ out. push ( ' ' ) ;
526+ let data_chunk = data_lines. get ( line_idx) . map ( |s| s. as_str ( ) ) . unwrap_or ( "" ) ;
527+ let c_data = if !data_chunk. is_empty ( ) {
528+ ctp ( data_chunk, FLAMINGO ) . to_string ( )
529+ } else {
530+ String :: new ( )
531+ } ;
532+ let data_vlen = visible_len ( & c_data) ;
533+ out. push_str ( & c_data) ;
534+ out. push_str ( & " " . repeat ( w_data. saturating_sub ( data_vlen) ) ) ;
535+ out. push ( ' ' ) ;
536+ out. push_str ( & v. to_string ( ) ) ;
537+
538538 out. push ( '\n' ) ;
539539 }
540540 }
@@ -622,7 +622,7 @@ pub fn enum_separator_row() -> EnumRow {
622622/// Render a scan results table with Catppuccin-styled box-drawing
623623pub fn render_scan_table ( devices : & [ crate :: scan:: ScannedDevice ] ) -> String {
624624 let tw = term_width ( ) ;
625- let headers = [ "Address" , "Type" , "RSSI" , "Name" ] ;
625+ let headers = [ "Address" , "Type" , "RSSI" , "Conn" , " Name"] ;
626626 let ncols = headers. len ( ) ;
627627
628628 // Measure column widths from content
@@ -633,15 +633,16 @@ pub fn render_scan_table(devices: &[crate::scan::ScannedDevice]) -> String {
633633 w[ 1 ] = w[ 1 ] . max ( type_str. len ( ) ) ;
634634 let rssi_str = dev. rssi . map ( |r| format ! ( "{} dBm" , r) ) . unwrap_or_else ( || "n/a" . into ( ) ) ;
635635 w[ 2 ] = w[ 2 ] . max ( rssi_str. len ( ) ) ;
636+ // w[3] = "Conn" column, fixed width from header is sufficient ("Yes"/"No"/"?")
636637 let name = dev. name . as_deref ( ) . unwrap_or ( "" ) ;
637- w[ 3 ] = w[ 3 ] . max ( name. len ( ) ) ;
638+ w[ 4 ] = w[ 4 ] . max ( name. len ( ) ) ;
638639 }
639640
640641 // Cap name column to fit terminal
641642 let overhead = ncols + 1 + ncols * 2 ; // borders + padding
642- let fixed = w[ 0 ] + w[ 1 ] + w[ 2 ] + overhead;
643- let max_name = tw. saturating_sub ( fixed) . max ( headers[ 3 ] . len ( ) ) . max ( 8 ) ;
644- w[ 3 ] = w[ 3 ] . min ( max_name) ;
643+ let fixed = w[ 0 ] + w[ 1 ] + w[ 2 ] + w [ 3 ] + overhead;
644+ let max_name = tw. saturating_sub ( fixed) . max ( headers[ 4 ] . len ( ) ) . max ( 8 ) ;
645+ w[ 4 ] = w[ 4 ] . min ( max_name) ;
645646
646647 let mut out = String :: new ( ) ;
647648 let b = ctp ( "─" , SURFACE1 ) ;
@@ -693,15 +694,20 @@ pub fn render_scan_table(devices: &[crate::scan::ScannedDevice]) -> String {
693694 let addr_str = format ! ( "{}" , dev. address) ;
694695 let type_str = format_addr_type ( dev. addr_type ) ;
695696 let rssi_str = dev. rssi . map ( |r| format ! ( "{} dBm" , r) ) . unwrap_or_else ( || "n/a" . into ( ) ) ;
697+ let conn_str = match dev. connectable {
698+ Some ( true ) => "Yes" ,
699+ Some ( false ) => "No" ,
700+ None => "?" ,
701+ } ;
696702 let name = dev. name . as_deref ( ) . unwrap_or ( "" ) ;
697703 // Truncate name if too long
698- let name_display = if name. len ( ) > w[ 3 ] {
699- & name[ ..w[ 3 ] ]
704+ let name_display = if name. len ( ) > w[ 4 ] {
705+ & name[ ..w[ 4 ] ]
700706 } else {
701707 name
702708 } ;
703709
704- let fields: Vec < String > = vec ! [ addr_str, type_str, rssi_str, name_display. to_string( ) ] ;
710+ let fields: Vec < String > = vec ! [ addr_str, type_str, rssi_str, conn_str . to_string ( ) , name_display. to_string( ) ] ;
705711
706712 out. push_str ( & v. to_string ( ) ) ;
707713 for ( i, field) in fields. iter ( ) . enumerate ( ) {
@@ -710,7 +716,12 @@ pub fn render_scan_table(devices: &[crate::scan::ScannedDevice]) -> String {
710716 0 => ctp_bold ( field, ROSEWATER ) . to_string ( ) ,
711717 1 => ctp ( field, LAVENDER ) . to_string ( ) ,
712718 2 => colorize_rssi ( field, dev. rssi ) ,
713- 3 => {
719+ 3 => match dev. connectable {
720+ Some ( true ) => ctp_bold ( field, GREEN ) . to_string ( ) ,
721+ Some ( false ) => ctp ( field, RED ) . to_string ( ) ,
722+ None => ctp ( field, OVERLAY0 ) . to_string ( ) ,
723+ } ,
724+ 4 => {
714725 if field. is_empty ( ) {
715726 ctp ( "(unknown)" , OVERLAY0 ) . to_string ( )
716727 } else {
0 commit comments