@@ -483,42 +483,61 @@ fn highlight_lines(err: &mut EmitterWriter,
483
483
// how many digits must be indent past?
484
484
while num > 0 { num /= 10 ; digits += 1 ; }
485
485
486
- // indent past |name:## | and the 0-offset column location
487
- let left = fm. name . len ( ) + digits + lo. col . to_usize ( ) + 3 ;
488
486
let mut s = String :: new ( ) ;
489
487
// Skip is the number of characters we need to skip because they are
490
488
// 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 ;
492
490
for _ in 0 ..skip {
493
491
s. push ( ' ' ) ;
494
492
}
495
493
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 ; }
498
500
// Whenever a tab occurs on the previous line, we insert one on
499
501
// the error-point-squiggly-line as well (instead of a space).
500
502
// That way the squiggly line will usually appear in the correct
501
503
// 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
+ }
506
514
}
507
- }
508
515
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
+ }
517
536
}
537
+ try!( print_maybe_styled ( err,
538
+ & format ! ( "{}\n " , s) [ ] ,
539
+ term:: attr:: ForegroundColor ( lvl. color ( ) ) ) ) ;
518
540
}
519
- try!( print_maybe_styled ( err,
520
- & format ! ( "{}\n " , s) [ ] ,
521
- term:: attr:: ForegroundColor ( lvl. color ( ) ) ) ) ;
522
541
}
523
542
Ok ( ( ) )
524
543
}
@@ -559,12 +578,28 @@ fn custom_highlight_lines(w: &mut EmitterWriter,
559
578
}
560
579
let last_line_start = format ! ( "{}:{} " , fm. name, lines[ lines. len( ) -1 ] +1 ) ;
561
580
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 ) ;
564
582
let mut s = String :: new ( ) ;
565
583
for _ in 0 ..skip {
566
584
s. push ( ' ' ) ;
567
585
}
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
+ }
568
603
s. push ( '^' ) ;
569
604
s. push ( '\n' ) ;
570
605
print_maybe_styled ( w,
0 commit comments