percent-format-0.0.1: src/Text/PercentFormat/Utils.hs
-- |
-- Module : Text.PercentFormat
-- Copyright : (c) 2016-2018 Rudy Matela
-- License : 3-Clause BSD (see the file LICENSE)
-- Maintainer : Rudy Matela <rudy@matela.com.br>
--
-- This file is part of PercentFormat a library for printf-style string
-- formatting.
--
-- This module provides miscellaneous utility functions.
module Text.PercentFormat.Utils
( maybeRead
, align
, rightAlign
, leftAlign
, showWithBase
, applyWhen
, intsToDigits
, theLast
, loop
, none
, integerToDigits
)
where
-- TODO: document this module more thoroughly
import Data.Maybe (listToMaybe)
import Data.List (unfoldr)
import Data.Char (intToDigit)
-- | Reads a value encoded as a string,
-- return 'Just' the value or 'Nothing' on error.
maybeRead :: Read a => String -> Maybe a
-- TODO: Use readsPrec to implement this.
maybeRead = listToMaybe . map fst . reads
align :: Bool -> Char -> Int -> String -> String
align left = if left
then leftAlign
else rightAlign
-- | @rightAlign c w s@ aligns 'String' @s@ to the right
-- in a field of width @w@ using 'Char' @c@ as padding.
--
-- > right ' ' 5 "123"
-- " 123"
rightAlign :: Char -> Int -> String -> String
rightAlign c width s | width <= len = s
| otherwise = replicate (width - len) c ++ s
where
len = length s
-- | @left c w s@ aligns 'String' @s@ to the left
-- in a field of width @w@ using 'Char' @c@ as padding.
--
-- > left ' ' 5 "123"
-- "123 "
leftAlign :: Char -> Int -> String -> String
leftAlign c width s | width <= len = s
| otherwise = s ++ replicate (width - len) c
where
len = length s
-- | @showWithBase b n@ returns a string representation of @n@ in base @b@.
--
-- > showWithBase 2 10
-- "1010"
-- > showWithBase 16 49406
-- "c0f3"
-- > showWithBase 10 (-1234)
-- "-1234"
showWithBase :: Integral a => Int -> a -> String
showWithBase b 0 = "0"
showWithBase b n | n < 0 = '-':showWithBase b (abs n)
| otherwise = map intToDigit $ integerToDigits b n
-- | Given an integer, returns a list of digits. Signal is ignored.
integerToDigits :: Integral a => Int -> a -> [Int]
integerToDigits b =
map fromIntegral
. reverse
. unfoldr (\n -> listToMaybe [swap $ n `divMod` fromIntegral b | n /= 0])
. abs
where
swap (x,y) = (y,x) -- not available on Hugs
applyWhen :: Bool -> (a -> a) -> a -> a
applyWhen True f x = f x
applyWhen False f x = x
intsToDigits :: [Int] -> String
intsToDigits = map intToDigit
theLast :: Int -> [a] -> [a]
theLast n xs = drop (length xs - n) xs
-- | Like cycle, but return an empty list when the source list is empty.
loop :: [a] -> [a]
loop [] = []
loop xs = cycle xs
none :: (a -> Bool) -> [a] -> Bool
none p = not . or . map p