NAME

Term::Fabulous::Widget::Table::Mutator - Ready-made mutators for table columns

SYNOPSIS

use Term::Fabulous::Widget::Table;
use Term::Fabulous::Widget::Table::Mutator qw(datetime number bytes boolean lookup truncate);

my $table = Term::Fabulous::Widget::Table->new(
	id      => 'files',
	columns => [
		{ key => 'name',     title => 'Name', mutator => truncate(30) },
		{ key => 'size',     title => 'Size', type => 'number', mutator => bytes() },
		{ key => 'modified', title => 'Modified', type => 'date', mutator => datetime('%d.%m.%Y %H:%M') },
		{ key => 'price',    title => 'Price', type => 'number', mutator => number( decimals => 2, prefix => '$' ) },
		{ key => 'shared',   title => 'Shared', mutator => boolean( 'yes', '' ) },
		{ key => 'state',    title => 'State', mutator => lookup( { r => 'running', s => 'sleeping' }, default => '?' ) },
	],
);

DESCRIPTION

A mutator turns the raw value of a table cell into the text the cell shows: a code reference called as $mutator->( $value, $row ) with the raw value and a copy of the row's data, returning the text. Give a column one, or an array reference of several that run one after the other, with its mutator option (see "mutator" in Term::Fabulous::Widget::Table::Column). The table keeps the raw value for sorting and, unless told otherwise, for filtering.

This module makes the common ones. Each function below returns a new mutator; nothing is exported by default, :all exports everything. Unknown options die. Every mutator turns a blank value (undef, and except for "boolean" and "lookup" also '') into '', and a value it cannot read (a word where a number belongs) into that value as text, so bad data stays visible.

FUNCTIONS

datetime

datetime()                          # 2024-05-03 14:30
datetime('%d.%m.%Y %H:%M:%S')
datetime( '%H:%M', utc => 1 )

A date or time in a "strftime" in POSIX format, default '%Y-%m-%d %H:%M'. The value may be epoch seconds, a date string (2024-05-03 14:30) or an object with an epoch method (see "date_epoch" in Term::Fabulous::Widget::Table::Value). Local time, or UTC with utc => 1.

date

date()             # 2024-05-03
date('%e %b %Y')   #  3 May 2024

"datetime" with the default format '%Y-%m-%d'.

number

number()                                      # 1234567.5 -> 1,234,567.5
number( decimals => 2 )                       # 1,234,567.50
number( decimals => 0, separator => '.' )     # 1.234.568
number( decimals => 2, separator => "\x{202F}", point => ',', suffix => ' EUR' )

A number with a separator between groups of three digits. Options: decimals (default: as many as the value has), separator (default ',', '' for none), point (the decimal point, default '.'), prefix and suffix (default '').

percent

percent()                     # 0.153 -> 15%
percent( decimals => 1 )      # 15.3%
percent( scale => 1 )         # 15.3 -> 15%

A fraction as a percentage. Options: decimals (default 0), scale (what the value is multiplied by, default 100; use 1 for values that are percentages already), separator and point (as for "number").

bytes

bytes()                         # 1536 -> 1.5 KiB
bytes( binary => 0 )            # 1536 -> 1.5 kB
bytes( decimals => 0 )          # 2 KiB

A size in bytes with a unit: B, KiB, MiB, GiB, ... (steps of 1024), or with binary => 0 B, kB, MB, GB, ... (steps of 1000). Option decimals, default 1; sizes below one step are shown as they are, with the unit B (512 B).

duration

duration()                  # 3725 -> 1h 02m
duration( parts => 3 )      # 1h 02m 05s

Seconds as days, hours, minutes and seconds, showing at most parts units (default 2) from the largest one that is not 0. Negative durations get a minus sign; 0 is 0s.

boolean

boolean()                     # yes / no
boolean( "\x{2714}", '' )    # a check mark, nothing for false

The first text for true values, the second for false ones (Perl's truth: 0, '' and '0' are false). undef gives ''.

lookup

lookup( { r => 'running', s => 'sleeping' } )
lookup( { 1 => 'high', 2 => 'normal' }, default => 'unknown' )

The text the hash gives for the value; a value it does not have gives default, or the value itself when there is no default. The hash is copied.

truncate

truncate(20)                       # long text cut to 20 columns, with an ellipsis
truncate( 20, ellipsis => '...' )

Text that is wider than that many terminal columns is cut so that it fits with the ellipsis (default "\x{2026}", one column). Wide characters count as two columns; no character is cut in half. To keep long text whole but narrow, give the column a maximum width instead (width => 'fit(0, 20)'), and it wraps.

sprintf_format

sprintf_format('%05d')       # 42 -> 00042
sprintf_format('%.1f %%')    # 12.34 -> 12.3 %

The value formatted with "sprintf" in perlfunc.

chain

chain( truncate(10), sub ( $text, $row ) { uc $text } )

One mutator that runs several in order, each getting the result of the one before. A column's mutator option does the same with an array reference.

WRITING YOUR OWN

Any code reference with this signature is a mutator:

my $temperature = sub ( $value, $row ) {
	return '' unless defined $value;
	return sprintf '%.1f %s', $value, $row->{unit} eq 'F' ? "\x{2109}" : "\x{2103}";
};

It should return a character string and not change $row (a copy is passed anyway). It is called again whenever the row or the column changes, and once per cell otherwise: the table keeps the results.

SEE ALSO

Term::Fabulous::Widget::Table, Term::Fabulous::Widget::Table::Column, Term::Fabulous::Widget::Table::Value, "DISPLAY TEXT AND MUTATORS" in Term::Fabulous::Manual::Tables, "Format cells: dates, numbers, sizes and flags (mutators)" in Term::Fabulous::Cookbook::Tables.