{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-} module Language.Haskell.Printf.Geometry where import Control.Applicative ( (<$>) ) import Control.Monad import Data.Maybe import Data.Monoid ( mempty ) import Data.Semigroup ( (<>) ) import Language.Haskell.PrintfArg import Parser.Types ( Adjustment(..) ) import qualified Buildable as B import StrUtils data Value buf = Value { valArg :: PrintfArg buf , valPrefix :: Maybe buf , valSign :: Maybe buf } deriving (Show) sign' :: (Num n, Ord n, B.Buildable buf) => PrintfArg n -> Maybe buf sign' pf | value pf < 0 = Just (B.singleton '-') | spaced pf = Just (B.singleton ' ') | signed pf = Just (B.singleton '+') | otherwise = Nothing padDecimal :: (B.Buildable buf, Eq v, Num v) => PrintfArg v -> buf -> buf padDecimal spec | prec spec == Just 0 && value spec == 0 = const mempty | otherwise = maybe id (`justifyRight` '0') (prec spec) prefix :: (Num n, Eq n, B.Buildable buf) => buf -> PrintfArg n -> Maybe buf prefix s pf = guard (prefixed pf && value pf /= 0) >> Just s fromPrintfArg :: B.Buildable buf => (n -> buf) -> (PrintfArg n -> Maybe buf) -> (PrintfArg n -> Maybe buf) -> PrintfArg n -> Value buf fromPrintfArg f b c a = Value (f <$> a) (b a) (c a) formatOne :: B.Buildable buf => Value buf -> buf formatOne Value {..} | Nothing <- width valArg = prefix' <> text | Just w <- width valArg = case adjustment valArg of Just ZeroPadded | isn'tDecimal || isNothing (prec valArg) -> prefix' <> justifyRight (w - B.size prefix') '0' text Just LeftJustified -> justifyLeft w ' ' (prefix' <> text) _ -> justify' w (prefix' <> text) | otherwise = error "unreachable" where isn'tDecimal = fieldSpec valArg `notElem` ("diouxX" :: String) justify' n | n < 0 = justifyLeft (abs n) ' ' | otherwise = justifyRight n ' ' prefix' = fromMaybe mempty valSign <> fromMaybe mempty valPrefix text = value valArg