@@ -483,42 +483,61 @@ fn highlight_lines(err: &mut EmitterWriter,
483483 // how many digits must be indent past?
484484 while num > 0 { num /= 10 ; digits += 1 ; }
485485
486- // indent past |name:## | and the 0-offset column location
487- let left = fm. name . len ( ) + digits + lo. col . to_usize ( ) + 3 ;
488486 let mut s = String :: new ( ) ;
489487 // Skip is the number of characters we need to skip because they are
490488 // part of the 'filename:line ' part of the previous line.
491- let skip = fm. name . len ( ) + digits + 3 ;
489+ let skip = fm. name . width ( false ) + digits + 3 ;
492490 for _ in 0 ..skip {
493491 s. push ( ' ' ) ;
494492 }
495493 if let Some ( orig) = fm. get_line ( lines. lines [ 0 ] ) {
496- for pos in 0 ..left - skip {
497- let cur_char = orig. as_bytes ( ) [ pos] as char ;
494+ let mut col = skip;
495+ let mut lastc = ' ' ;
496+ let mut iter = orig. chars ( ) . enumerate ( ) ;
497+ for ( pos, ch) in iter. by_ref ( ) {
498+ lastc = ch;
499+ if pos >= lo. col . to_usize ( ) { break ; }
498500 // Whenever a tab occurs on the previous line, we insert one on
499501 // the error-point-squiggly-line as well (instead of a space).
500502 // That way the squiggly line will usually appear in the correct
501503 // position.
502- match cur_char {
503- '\t' => s. push ( '\t' ) ,
504- _ => s. push ( ' ' ) ,
505- } ;
504+ match ch {
505+ '\t' => {
506+ col += 8 - col%8 ;
507+ s. push ( '\t' ) ;
508+ } ,
509+ c => for _ in 0 ..c. width ( false ) . unwrap_or ( 0 ) {
510+ col += 1 ;
511+ s. push ( ' ' ) ;
512+ } ,
513+ }
506514 }
507- }
508515
509- try!( write ! ( & mut err. dst, "{}" , s) ) ;
510- let mut s = String :: from_str ( "^" ) ;
511- let hi = cm. lookup_char_pos ( sp. hi ) ;
512- if hi. col != lo. col {
513- // the ^ already takes up one space
514- let num_squigglies = hi. col . to_usize ( ) - lo. col . to_usize ( ) - 1 ;
515- for _ in 0 ..num_squigglies {
516- s. push ( '~' ) ;
516+ try!( write ! ( & mut err. dst, "{}" , s) ) ;
517+ let mut s = String :: from_str ( "^" ) ;
518+ let count = match lastc {
519+ // Most terminals have a tab stop every eight columns by default
520+ '\t' => 8 - col%8 ,
521+ _ => lastc. width ( false ) . unwrap_or ( 1 ) ,
522+ } ;
523+ col += count;
524+ s. extend ( :: std:: iter:: repeat ( '~' ) . take ( count - 1 ) ) ;
525+ let hi = cm. lookup_char_pos ( sp. hi ) ;
526+ if hi. col != lo. col {
527+ for ( pos, ch) in iter {
528+ if pos >= hi. col . to_usize ( ) { break ; }
529+ let count = match ch {
530+ '\t' => 8 - col%8 ,
531+ _ => ch. width ( false ) . unwrap_or ( 0 ) ,
532+ } ;
533+ col += count;
534+ s. extend ( :: std:: iter:: repeat ( '~' ) . take ( count) ) ;
535+ }
517536 }
537+ try!( print_maybe_styled ( err,
538+ & format ! ( "{}\n " , s) [ ] ,
539+ term:: attr:: ForegroundColor ( lvl. color ( ) ) ) ) ;
518540 }
519- try!( print_maybe_styled ( err,
520- & format ! ( "{}\n " , s) [ ] ,
521- term:: attr:: ForegroundColor ( lvl. color ( ) ) ) ) ;
522541 }
523542 Ok ( ( ) )
524543}
@@ -559,12 +578,28 @@ fn custom_highlight_lines(w: &mut EmitterWriter,
559578 }
560579 let last_line_start = format ! ( "{}:{} " , fm. name, lines[ lines. len( ) -1 ] +1 ) ;
561580 let hi = cm. lookup_char_pos ( sp. hi ) ;
562- // Span seems to use half-opened interval, so subtract 1
563- let skip = last_line_start. len ( ) + hi. col . to_usize ( ) - 1 ;
581+ let skip = last_line_start. width ( false ) ;
564582 let mut s = String :: new ( ) ;
565583 for _ in 0 ..skip {
566584 s. push ( ' ' ) ;
567585 }
586+ if let Some ( orig) = fm. get_line ( lines[ 0 ] ) {
587+ let iter = orig. chars ( ) . enumerate ( ) ;
588+ for ( pos, ch) in iter {
589+ // Span seems to use half-opened interval, so subtract 1
590+ if pos >= hi. col . to_usize ( ) - 1 { break ; }
591+ // Whenever a tab occurs on the previous line, we insert one on
592+ // the error-point-squiggly-line as well (instead of a space).
593+ // That way the squiggly line will usually appear in the correct
594+ // position.
595+ match ch {
596+ '\t' => s. push ( '\t' ) ,
597+ c => for _ in 0 ..c. width ( false ) . unwrap_or ( 0 ) {
598+ s. push ( ' ' ) ;
599+ } ,
600+ }
601+ }
602+ }
568603 s. push ( '^' ) ;
569604 s. push ( '\n' ) ;
570605 print_maybe_styled ( w,
0 commit comments