{-# 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
{ PrettyCfg -> Int
pc_decimals :: !Int
, PrettyCfg -> Maybe Char
pc_thousandsSep :: !(Maybe Char)
, PrettyCfg -> Char
pc_decimalSep :: !Char
}
prettyF :: RealFrac i => PrettyCfg -> i -> T.Text
prettyF :: PrettyCfg -> i -> Text
prettyF PrettyCfg{Char
Int
Maybe Char
pc_decimalSep :: Char
pc_thousandsSep :: Maybe Char
pc_decimals :: Int
pc_decimalSep :: PrettyCfg -> Char
pc_thousandsSep :: PrettyCfg -> Maybe Char
pc_decimals :: PrettyCfg -> Int
..} i
n =
let tpow :: Int
tpow = Int
10 Int -> Int -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
pc_decimals
lshift :: i
lshift = i
n i -> i -> i
forall a. Num a => a -> a -> a
* Int -> i
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
tpow
lshiftr :: Int
lshiftr = i -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round i
lshift
lshifti' :: Int
lshifti' = Int -> Int
forall a. Num a => a -> a
abs Int
lshiftr
intPart :: Int
intPart = Int
lshifti' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
tpow
decPart :: Int
decPart = Int
lshifti' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
intPart Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
tpow
preDecimal :: Text
preDecimal =
if Int
lshiftr Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
then Maybe Char -> Int -> Text
prettyI Maybe Char
pc_thousandsSep (Int
intPart Int -> Int -> Int
forall a. Num a => a -> a -> a
* (-Int
1))
else Maybe Char -> Int -> Text
prettyI Maybe Char
pc_thousandsSep Int
intPart
postDecimal :: Text
postDecimal =
if Int
pc_decimals Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
then Char -> Text -> Text
T.cons Char
pc_decimalSep (Int -> Char -> Text -> Text
T.justifyRight Int
pc_decimals Char
'0' (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
decPart)
else Text
""
in Text
preDecimal Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
postDecimal
prettyI :: Maybe Char -> Int -> T.Text
prettyI :: Maybe Char -> Int -> Text
prettyI Maybe Char
tsep Int
n =
let ni :: Text
ni = String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a. Num a => a -> a
abs Int
n
nis :: Text
nis =
case Maybe Char
tsep of
Just Char
s ->
Text -> [Text] -> Text
T.intercalate (Char -> Text
T.singleton Char
s) ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$
[Text] -> [Text]
forall a. [a] -> [a]
reverse ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
T.reverse ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Int -> Text -> [Text]
T.chunksOf Int
3 (Text -> [Text]) -> Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Text
T.reverse Text
ni
Maybe Char
Nothing ->
Text
ni
in if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then Text
"-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
nis else Text
nis