format-numbers-0.1.0.1: src/Data/Text/Format/Numbers.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Data.Text.Format.Numbers
( PrettyCfg(..)
, prettyF
, prettyI
)
where
import Data.Monoid
import qualified Data.Text as T
data PrettyCfg
= PrettyCfg
{ pc_decimals :: !Int
-- ^ Decimals to display
, pc_thousandsSep :: !(Maybe Char)
-- ^ Optional thousands separator
, pc_decimalSep :: !Char
-- ^ Decimal separator
}
-- | Pretty print any number given a configuration
prettyF :: RealFrac i => PrettyCfg -> i -> T.Text
prettyF PrettyCfg{..} n =
let tpow = 10 ^ pc_decimals
lshift = n * fromIntegral tpow
lshiftr = round lshift
lshifti' = abs lshiftr
intPart = lshifti' `div` tpow
decPart = lshifti' - intPart * tpow
preDecimal =
if lshiftr < 0
then prettyI pc_thousandsSep (intPart * (-1))
else prettyI pc_thousandsSep intPart
postDecimal =
if pc_decimals > 0
then T.cons pc_decimalSep (T.justifyRight pc_decimals '0' $ T.pack $ show decPart)
else ""
in preDecimal <> postDecimal
-- | Pretty print an 'Int' given an optional thousands separator
prettyI :: Maybe Char -> Int -> T.Text
prettyI tsep n =
let ni = T.pack $ show $ abs n
nis =
case tsep of
Just s ->
T.intercalate (T.singleton s) $
reverse $ map T.reverse $ T.chunksOf 3 $ T.reverse ni
Nothing ->
ni
in if n < 0 then "-" <> nis else nis