module Text.Printf.Safe.Combinators (
type (<>), (><), (%), (+++),
s, _S, _shows,
base, d, d', o, o', b, b', h, h', f) where
import Data.Char (intToDigit)
import Data.Type.Equality ((:~:) (..), gcastWith)
import Numeric (showFloat, showIntAtBase)
import Text.Printf.Safe.Core (Printf (..), Formatter)
type family (<>) xs ys where
(<>) '[] xs = xs
(<>) (x ': xs) ys = x ': (xs <> ys)
appPrf :: Printf ts -> Printf ps -> Printf (ts <> ps)
appPrf EOS ps = ps
appPrf (str :<> ts) ps = str :<> appPrf ts ps
appPrf (fm :% ts) ps = fm :% appPrf ts ps
appNil :: Printf ts -> (ts <> '[]) :~: ts
appNil EOS = Refl
appNil (_ :<> a) = appNil a
appNil (_ :% bs) = case appNil bs of Refl -> Refl
(><) :: Printf ts -> String -> Printf ts
xs >< str = gcastWith (appNil xs) $ appPrf xs (str :<> EOS)
(%) :: Printf ts -> (a -> String) -> Printf (ts <> '[a])
(%) xs p = appPrf xs (p :% EOS)
(+++) :: Printf ts -> Printf ps -> Printf (ts <> ps)
(+++) = appPrf
infixr 5 +++
infixl 5 ><, %
s :: Formatter String
s = id
_S :: Show a => Formatter a
_S = show
_shows :: (a -> ShowS) -> Formatter a
_shows fmt = flip fmt ""
base :: (Show a, Integral a)
=> a
-> Maybe (Char, Int)
-> Formatter a
base adic mpd a =
let ans = showIntAtBase adic intToDigit a ""
in maybe "" (\(c,dig) -> replicate (dig length ans) c) mpd ++ ans
d' :: (Show a, Integral a) => Char -> Int -> Formatter a
d' c i = base 10 (Just (c,i))
d :: (Show a, Integral a) => Formatter a
d = base 10 Nothing
o' :: (Show a, Integral a) => Char -> Int -> Formatter a
o' c i = base 8 (Just (c,i))
o :: (Show a, Integral a) => Formatter a
o = base 8 Nothing
b' :: (Show a, Integral a) => Char -> Int -> Formatter a
b' c i = base 2 (Just (c,i))
b :: (Show a, Integral a) => Formatter a
b = base 2 Nothing
h' :: (Show a, Integral a) => Char -> Int -> Formatter a
h' c i = base 16 (Just (c,i))
h :: (Show a, Integral a) => Formatter a
h = base 16 Nothing
f :: RealFloat a => Formatter a
f = _shows showFloat