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.

source · imports t: libs/Strings/src/Strings.xtl; q: libs/Lists/src/Lists.xtl

digits : Char

value (private) · line 15
digits ← ⎕D
Used in: ʰp̲added

Fixed decimals

ʰp̲added : Int -> Int -> Char

function (private) · line 20

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

function (private) · line 23

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
}
Used in: ˡf̲ixed

ˡf̲ixed : Num a => Int -> a -> Box Char

function · line 32

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

function (private) · line 38

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

function (private) · line 46

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
}
Used in: ˡt̲housands

ʰa̲mount1 : Num a => Int -> a -> Char

function (private) · line 52

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
}
Used in: ˡa̲mount

ˡt̲housands : Num a => a -> Box Char

function · line 62

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

function · line 66

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

function · line 69

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

function (private) · line 74

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

function · line 78

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

function (private) · line 84

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 "-+.,%" }
Used in: ˡt̲able

ˡt̲able : Box Char -> Char

function · line 91

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
}