librarylibs/Format/src/Format.xtl
Format: number formatting -- fixed decimals, thousands separators, percentages, aligned columns, text tables. Import it with an alias of your choice: "f:" u_se< "Format". Put libs/Format/src on XETAL_PATH ("just path"); the reference is libs/Format/docs. Names with l: are exported; those under h: are private to this file.
X_eTaL's f_ormat has no width or precision yet (dyadic format is on its wish list): these build the text from the digits. A formatted list is a list of texts (Box Char), one per number, ready for f:c_olumn or f:t_able.
Fixed decimals
ʰp̲added : Int -> Int -> Char
The k decimal digits of a whole number d, leading zeros kept.
ʰp̲added ← { k d → k = 0 ? ""◆ (1 + (k r̲eshape 10) e̲ncode d) s̲elect digits }
ʰo̲ne : Num a => Int -> a -> Char
One number with n decimals, rounded half away from zero.
ʰo̲ne ← { n x → s ← f̲loor 0.5 + (a̲bs f̲loat x) × f̲loat 10 ^ n w ← s d̲iv 10 ^ n sign ← ((x < 0) ∧ s > 0) r̲eplicate "-" n = 0 ? sign c̲at f̲ormat w sign c̲at (f̲ormat w) c̲at "." c̲at n ʰp̲added s m̲od 10 ^ n }
ˡf̲ixed : Num a => Int -> a -> Box Char
n f_ixed v: each number of v with exactly n decimals (n >= 0).
ˡf̲ixed ← { n v → '{ x → n ʰo̲ne x } m̲ap r̲avel v }
Thousands and money
ʰc̲ommas : a -> Char
A whole number >= 0 with a comma between each group of three digits: padded in front to a multiple of 3, cut into rows of 3, joined.
ʰc̲ommas ← { w → d ← f̲ormat w p ← 3 × c̲eiling (f̲loat t̲ally d) ÷ 3.0 rows ← ((p d̲iv 3) c̲at 3) r̲eshape (n̲eg p) t̲ake d ᵗt̲rimStart "," ᵗj̲oin '{ i → i s̲elect rows } m̲ap r̲ange p d̲iv 3 }
ʰg̲rouped : Num a => a -> Char
One number rounded to a whole number, its thousands separated.
ʰg̲rouped ← { x → w ← f̲loor 0.5 + f̲loat a̲bs x (((x < 0) ∧ w > 0) r̲eplicate "-") c̲at ʰc̲ommas w }
ʰa̲mount1 : Num a => Int -> a -> Char
One number with n decimals and its thousands separated.
ʰa̲mount1 ← { n x → s ← f̲loor 0.5 + (a̲bs f̲loat x) × f̲loat 10 ^ n w ← s d̲iv 10 ^ n sign ← ((x < 0) ∧ s > 0) r̲eplicate "-" n = 0 ? sign c̲at ʰc̲ommas w sign c̲at (ʰc̲ommas w) c̲at "." c̲at n ʰp̲added s m̲od 10 ^ n }
ˡt̲housands : Num a => a -> Box Char
t_housands v: each number of v, rounded to a whole number, with its thousands separated by commas.
ˡt̲housands ← { v → 'ʰg̲rouped m̲ap r̲avel v }
ˡa̲mount : Num a => Int -> a -> Box Char
n a_mount v: each number of v with n decimals and its thousands separated by commas (money: 2 f:a_mount 1324.69 is 1,324.69).
ˡa̲mount ← { n v → '{ x → n ʰa̲mount1 x } m̲ap r̲avel v }
ˡp̲ercent : Num a => Int -> a -> Box Char
n p_ercent v: each fraction of v as a percentage with n decimals.
ˡp̲ercent ← { n v → '{ t → (d̲isclose t) c̲at "%" } m̲ap n ˡf̲ixed 100.0 × f̲loat v }
Tables
ʰr̲ows : Int -> Box a -> a
A list of texts as a character matrix, one per row, w wide.
ʰr̲ows ← { w list → ((t̲ally list) c̲at w) r̲eshape q:r̲aze list }
ˡc̲olumn : Box a -> a
c_olumn list: the texts of a list right-aligned under each other (a character matrix), as numbers are set in a column.
ˡc̲olumn ← { list → w ← 'm̲ax r̲/ '{ t̲ally d̲isclose ⍵ } e̲ach list w ʰr̲ows '{ t → w ᵗp̲adLeft d̲isclose t } m̲ap list }
ʰn̲umeric? : Truthy a => Char -> a
Whether a text reads as a number (set right-aligned in a table).
ʰn̲umeric? ← { t → 0 = t̲ally t ? 0 = 1◆ '∧ r̲/ t m̲ember? ⎕D c̲at "-+.,%" }
ˡt̲able : Box Char -> Char
t_able cells: a matrix of texts (Box Char), its first row the header, as a character matrix: columns two spaces apart, each as wide as its widest text, a column of numbers (every cell under the header) right-aligned with its header, other columns left-aligned, a rule under the header.
ˡt̲able ← { cells → w ← 'm̲ax r̲/ '{ t̲ally d̲isclose ⍵ } e̲ach cells ⍝ each column's width num ← '∧ r̲/ 1 d̲rop '{ ʰn̲umeric? d̲isclose ⍵ } e̲ach cells ws ← r̲avel (s̲hape cells) r̲eshape w ⍝ each cell's width ns ← r̲avel (s̲hape cells) r̲eshape num ⍝ each cell's alignment cs ← r̲avel cells p ← (s̲hape cells) r̲eshape '{ i → n ← f̲irst i s̲elect ws c ← d̲isclose i s̲elect cs f̲irst i s̲elect ns ? n ᵗp̲adLeft c n ᵗp̲adRight c } m̲ap r̲ange t̲ally cs rows ← '{ i → " " ᵗj̲oin i s̲elect p } m̲ap r̲ange t̲ally p rule ← " " ᵗj̲oin '{ n → n r̲eshape "-" } m̲ap w all ← (1 t̲ake rows) c̲at (e̲nclose rule) c̲at 1 d̲rop rows (t̲ally rule) ʰr̲ows all }