{-# LANGUAGE RankNTypes #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS -Wall #-} -- | -- Module : Formatting.Formatters -- Copyright : (c) 2013 Chris Done, 2013 Shachaf Ben-Kiki -- License : BSD3 -- Maintainer : chrisdone@gmail.com -- Stability : experimental -- Portability : GHC -- -- Formatting functions. module Formatting.Formatters ( -- * Text/string types text, stext, string, builder, fconst, -- * Numbers int, float, expt, fixed, prec, shortest, commas, -- * Padding left, right, -- * Bases hex, -- * Buildables build, Buildable ) where import Formatting.Holey import Data.Monoid import qualified Data.Text as S import qualified Data.Text as T import Data.Text.Buildable (Buildable) import qualified Data.Text.Buildable as B (build) import qualified Data.Text.Format as T import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as LT import Data.Text.Lazy.Builder (Builder) import qualified Data.Text.Lazy.Builder as T -- | Output a lazy text. text :: Format Text text = later T.fromLazyText -- | Render an integer using hexadecimal notation. (No leading 0x is -- added.) hex :: Integral a => Format a hex = later T.hex -- | Output a strict text. stext :: Format S.Text stext = later T.fromText -- | Output a string. string :: Format String string = later (T.fromText . T.pack) -- | Build a builder. builder :: Format Builder builder = later id -- | Like `const` but for formatters. fconst :: Builder -> Format a fconst m = later (const m) -- | Build anything that implements the "Buildable" class. build :: Buildable a => Format a build = later B.build -- | Render an integral e.g. 123 -> \"123\", 0 -> \"0\". int :: Integral a => Format a int = later T.shortest -- | Render some floating point with the usual notation, e.g. 123.32 => \"123.32\" float :: Real a => Format a float = later (T.shortest) -- | Render a floating point number using scientific/engineering -- notation (e.g. 2.3e123), with the given number of decimal places. expt :: Real a => Int -> Format a expt i = later (T.expt i) -- | Render a floating point number using normal notation, with the -- given number of decimal places. fixed :: Real a => Int -> Format a fixed i = later (T.fixed i) -- | Render a floating point number, with the given number of digits -- of precision. Uses decimal notation for values between 0.1 and -- 9,999,999, and scientific notation otherwise. prec :: Real a => Int -> Format a prec i = later (T.prec i) -- | Render a floating point number using the smallest number of -- digits that correctly represent it. shortest :: Real a => Format a shortest = later T.shortest -- | Pad the left hand side of a string until it reaches k characters -- wide, if necessary filling with character c. left :: Buildable a => Int -> Char -> Format a left i c = later (T.left i c) -- | Pad the right hand side of a string until it reaches k characters -- wide, if necessary filling with character c. right :: Buildable a => Int -> Char -> Format a right i c = later (T.right i c) -- | Add commas to an integral, e.g 12000 -> \ "12,000". commas :: (Buildable n,Integral n) => Format n commas = later (commaize) where commaize = T.fromLazyText . LT.reverse . foldr merge "" . LT.zip ("000" <> cycle' ",00") . LT.reverse . T.toLazyText . B.build merge (f,c) rest | f == ',' = "," <> LT.singleton c <> rest | otherwise = LT.singleton c <> rest cycle' xs = xs <> cycle' xs