|
Lines 394-419
a bad character, and its ordinal C<$char_ord>, returns a two-line string:
Link Here
|
| 394 |
=over 4 |
394 |
=over 4 |
| 395 |
|
395 |
|
| 396 |
=item * Line 1 – up to 30 characters of context either side of the bad |
396 |
=item * Line 1 – up to 30 characters of context either side of the bad |
| 397 |
character, with the bad character replaced by a C<[U+XXXX]> marker and |
397 |
character, with the bad character replaced by a visible glyph (Unicode |
| 398 |
ellipses when the window is truncated. |
398 |
Control Pictures U+2400–U+241F for C0 controls, C<␡> for DEL, C<?> |
|
|
399 |
otherwise) and ellipses when the window is truncated. |
| 399 |
|
400 |
|
| 400 |
=item * Line 2 – a caret (C<^>) aligned beneath the start of the marker. |
401 |
=item * Line 2 – a caret (C<^>) aligned beneath the visible glyph. |
| 401 |
|
402 |
|
| 402 |
=back |
403 |
=back |
| 403 |
|
404 |
|
| 404 |
Example output (4-space indent): |
405 |
Example output (4-space indent): |
| 405 |
|
406 |
|
| 406 |
...arr \ [U+0008]$btxt V $2rdac ontent |
407 |
t $xtac arr␈\ $btxt V $2rdac ontent |
| 407 |
^ |
408 |
^ |
| 408 |
|
409 |
|
| 409 |
=cut |
410 |
=cut |
| 410 |
|
411 |
|
| 411 |
sub _context_snippet { |
412 |
sub _context_snippet { |
| 412 |
my ( $chars_ref, $pos_0, $char_ord ) = @_; |
413 |
my ( $chars_ref, $pos_0, $char_ord ) = @_; |
| 413 |
|
414 |
|
| 414 |
my $marker = sprintf '[U+%04X]', $char_ord; |
415 |
# Visible stand-in for the removed character: |
| 415 |
my $last = $#{$chars_ref}; |
416 |
# C0 controls (U+0000–U+001F) → Unicode Control Pictures (U+2400–U+241F) |
| 416 |
my $win = 30; |
417 |
# DEL (U+007F) → U+2421 SYMBOL FOR DELETE (␡) |
|
|
418 |
# anything else → U+FFFD REPLACEMENT CHARACTER (?) |
| 419 |
my $visible = |
| 420 |
$char_ord <= 0x1F ? chr( $char_ord + 0x2400 ) |
| 421 |
: $char_ord == 0x7F ? "\x{2421}" |
| 422 |
: "\x{FFFD}"; |
| 423 |
|
| 424 |
my $last = $#{$chars_ref}; |
| 425 |
my $win = 30; |
| 417 |
|
426 |
|
| 418 |
my $pre_start = ( $pos_0 > $win ) ? $pos_0 - $win : 0; |
427 |
my $pre_start = ( $pos_0 > $win ) ? $pos_0 - $win : 0; |
| 419 |
my $post_end = ( $pos_0 + $win < $last ) ? $pos_0 + $win : $last; |
428 |
my $post_end = ( $pos_0 + $win < $last ) ? $pos_0 + $win : $last; |
|
Lines 425-431
sub _context_snippet {
Link Here
|
| 425 |
my $suffix = ( $pos_0 + $win < $last ) ? '...' : ''; |
434 |
my $suffix = ( $pos_0 + $win < $last ) ? '...' : ''; |
| 426 |
|
435 |
|
| 427 |
my $indent = ' '; |
436 |
my $indent = ' '; |
| 428 |
my $line = "$indent$prefix$pre$marker$post$suffix"; |
437 |
my $line = "$indent$prefix$pre$visible$post$suffix"; |
| 429 |
my $caret_col = length($indent) + length($prefix) + length($pre); |
438 |
my $caret_col = length($indent) + length($prefix) + length($pre); |
| 430 |
|
439 |
|
| 431 |
return "$line\n" . ( ' ' x $caret_col ) . '^'; |
440 |
return "$line\n" . ( ' ' x $caret_col ) . '^'; |
| 432 |
- |
|
|