The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Text::ANSI::NonWideUtil - Routines for text containing ANSI color codes (non-wide functions only)

VERSION

This document describes version 0.21 of Text::ANSI::NonWideUtil (from Perl distribution Text-ANSI-Util), released on 2015-08-20.

DESCRIPTION

This module provides routines for dealing with text that contains ANSI color codes, e.g. for determining its length/width (excluding the color codes), stripping the color codes, extracting the color codes, and so on.

There is also a wide variant: Text::ANSI::WideUtil. The difference is that ::WideUtil can handle wide (full-width) Unicode characters, while ::NonWideUtil can also handle normal/halfwidth/ASCII characters.

FUNCTIONS

ta_detect($text) => BOOL

Return true if $text contains ANSI color codes, false otherwise.

ta_length($text) => INT

Count the number of characters in $text, while ignoring ANSI color codes. Equivalent to length(ta_strip($text)). See also: ta_mbswidth().

ta_length_height($text) => [INT, INT]

Like ta_length(), but also gives height (number of lines). For example, ta_length_height("foobar\nb\n") gives [6, 3].

ta_strip($text) => STR

Strip ANSI color codes from $text, returning the stripped text.

ta_extract_codes($text) => STR

This is the opposite of ta_strip(), return only the ANSI codes in $text.

ta_split_codes($text) => LIST

Split $text to a list containing alternating ANSI color codes and text. ANSI color codes are always on the second element, fourth, and so on. Example:

 ta_split_codes("");              # => ()
 ta_split_codes("a");             # => ("a")
 ta_split_codes("a\e[31m");       # => ("a", "\e[31m")
 ta_split_codes("\e[31ma");       # => ("", "\e[31m", "a")
 ta_split_codes("\e[31ma\e[0m");  # => ("", "\e[31m", "a", "\e[0m")
 ta_split_codes("\e[31ma\e[0mb"); # => ("", "\e[31m", "a", "\e[0m", "b")
 ta_split_codes("\e[31m\e[0mb");  # => ("", "\e[31m\e[0m", "b")

so you can do something like:

 my @parts = ta_split_codes($text);
 while (my ($text, $ansicode) = splice(@parts, 0, 2)) {
     ...
 }

ta_split_codes_single($text) => LIST

Like ta_split_codes() but each ANSI color code is split separately, instead of grouped together. This routine is currently used internally e.g. for ta_mbwrap() and ta_highlight() to trace color reset/replay codes.

ta_wrap($text, $width, \%opts) => STR

Like Text::WideChar::Util's wrap() except handles ANSI color codes. Perform color reset at the end of each line and a color replay at the start of subsequent line so the text is safe for combining in a multicolumn/tabular layout.

Options:

  • flindent => STR

    First line indent. See Text::WideChar::Util for more details.

  • slindent => STR

    First line indent. See Text::WideChar::Util for more details.

  • tab_width => INT (default: 8)

    First line indent. See Text::WideChar::Util for more details.

  • pad => BOOL (default: 0)

    If set to true, will pad each line to $width. This is convenient if you need the lines padded, saves calls to ta_pad().

  • return_stats => BOOL (default: 0)

    If set to true, then instead of returning the wrapped string, function will return [$wrapped, $stats] where $stats is a hash containing some information like max_word_width, min_word_width.

Performance: ~500/s on my Core i5 1.7GHz laptop for a ~1KB of text (with zero to moderate amount of color codes). As a comparison, Text::WideChar::Util's wrap() can do about 2000/s.

ta_add_color_resets(@text) => LIST

Make sure that a color reset command (add \e[0m) to the end of each element and a replay of all the color codes from the previous element, from the last color reset) to the start of the next element, and so on. Return the new list.

This makes each element safe to be combined with other array of text into a single line, e.g. in a multicolumn/tabular layout. An example:

Without color resets:

 my @col1 = split /\n/, "\e[31mred\nmerah\e[0m";
 my @col2 = split /\n/, "\e[32mgreen\e[1m\nhijau tebal\e[0m";

 printf "%s | %s\n", $col1[0], $col2[0];
 printf "%s | %s\n", $col1[1], $col2[1];

the printed output:

 \e[31mred | \e[32mgreen
 merah\e[0m | \e[1mhijau tebal\e[0m

The merah text on the second line will become green because of the effect of the last color command printed (\e[32m). However, with ta_add_color_resets():

 my @col1 = ta_add_color_resets(split /\n/, "\e[31mred\nmerah\e[0m");
 my @col2 = ta_add_color_resets(split /\n/, "\e[32mgreen\e[1m\nhijau tebal\e[0m");

 printf "%s | %s\n", $col1[0], $col2[0];
 printf "%s | %s\n", $col1[1], $col2[1];

the printed output (<...>) marks the code added by ta_add_color_resets():

 \e[31mred<\e[0m> | \e[32mgreen\e[1m<\e[0m>
 <\e[31m>merah\e[0m | <\e[32m\e[1m>hijau tebal\e[0m

All the cells are printed with the intended colors.

ta_pad($text, $width[, $which[, $padchar[, $truncate]]]) => STR

Return $text padded with $padchar to $width columns. $which is either "r" or "right" for padding on the right (the default if not specified), "l" or "left" for padding on the right, or "c" or "center" or "centre" for left+right padding to center the text.

$padchar is whitespace if not specified. It should be string having the width of 1 column.

Does *not* handle multiline text; you can split text by /\r?\n/ yourself.

ta_trunc($text, $width) => STR

Truncate $text to $width columns while still including all the ANSI color codes. This ensures that truncated text still reset colors, etc.

Does *not* handle multiline text; you can split text by /\r?\n/ yourself.

ta_highlight($text, $needle, $color) => STR

Highlight the first occurence of $needle in $text with <$color>, taking care not to mess up existing colors.

$needle can be a string or a Regexp object.

Implementation note: to not mess up colors, we save up all color codes from the last reset (\e[0m) before inserting the highlight color + highlight text. Then we issue \e[0m and the saved up color code to return back to the color state before the highlight is inserted. This is the same technique as described in ta_add_color_resets().

ta_highlight_all($text, $needle, $color) => STR

Like ta_highlight(), but highlight all occurences instead of only the first.

ta_substr($text, $pos, $len[ , $replacement ]) => STR

A bit like Perl's substr(). If $replacement is not specified, will return the substring. If $replacement is specified, will return $text with the substring replaced by $replacement.

SEE ALSO

Text::ANSI::WideUtil

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/Text-ANSI-Util.

SOURCE

Source repository is at https://github.com/perlancar/perl-Text-ANSI-Util.

BUGS

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Text-ANSI-Util

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

AUTHOR

perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.