module Yi.String (isBlank,
chomp,
capitalize,
capitalizeFirst,
dropSpace,
fillText,
onLines,
mapLines,
lines',
unlines',
padLeft, padRight,
commonTPrefix,
commonTPrefix',
listify,
showT,
overInit, overTail
) where
import Data.Char (isAlphaNum, isSpace, toLower, toUpper)
import Data.List (isSuffixOf)
import Data.Maybe (fromMaybe)
import Data.Monoid (mconcat, (<>))
import qualified Data.Text as T (Text, break, commonPrefixes, empty,
intercalate, pack, splitAt, splitOn, toUpper)
import qualified Yi.Rope as R (YiString, all, cons, head, init, intercalate,
last, length, lines', snoc, tail, unwords,
withText, words)
showT :: Show a => a -> T.Text
showT = T.pack . show
listify :: [R.YiString] -> R.YiString
listify t = '[' `R.cons` R.intercalate ", " t `R.snoc` ']'
commonTPrefix :: [T.Text] -> Maybe T.Text
commonTPrefix (x:y:xs) = case T.commonPrefixes x y of
Nothing -> Nothing
Just (p, _, _) -> commonTPrefix (p : xs)
commonTPrefix [x] = Just x
commonTPrefix _ = Nothing
commonTPrefix' :: [T.Text] -> T.Text
commonTPrefix' = fromMaybe T.empty . commonTPrefix
capitalize :: String -> String
capitalize [] = []
capitalize (c:cs) = toUpper c : map toLower cs
capitalizeFirst :: R.YiString -> R.YiString
capitalizeFirst = R.withText go
where
go x = case T.break isAlphaNum x of
(f, b) -> f <> case T.splitAt 1 b of
(h, hs) -> T.toUpper h <> hs
chomp :: String -> String -> String
chomp irs st
| irs `isSuffixOf` st
= let st' = reverse $ drop (length irs) (reverse st) in chomp irs st'
| otherwise = st
dropSpace :: String -> String
dropSpace = let f = reverse . dropWhile isSpace in f . f
isBlank :: R.YiString -> Bool
isBlank = R.all isSpace
fillText :: Int -> R.YiString -> [R.YiString]
fillText margin = map (R.unwords . reverse) . fill 0 [] . R.words
where
fill _ acc [] = [acc]
fill n acc (w:ws)
| n + R.length w >= margin = acc : fill (R.length w) [w] ws
| otherwise = fill (n + 1 + R.length w) (w:acc) ws
overInit :: (R.YiString -> R.YiString) -> R.YiString -> R.YiString
overInit f t = case (R.init t, R.last t) of
(Just xs, Just x) -> f xs `R.snoc` x
_ -> t
overTail :: (R.YiString -> R.YiString) -> R.YiString -> R.YiString
overTail f t = case (R.head t, R.tail t) of
(Just x, Just xs) -> x `R.cons` f xs
_ -> t
unlines' :: [T.Text] -> T.Text
unlines' = T.intercalate "\n"
lines' :: T.Text -> [T.Text]
lines' = T.splitOn "\n"
mapLines :: (R.YiString -> R.YiString) -> R.YiString -> R.YiString
mapLines f = onLines $ fmap f
onLines :: ([R.YiString] -> [R.YiString]) -> R.YiString -> R.YiString
onLines f = mconcat . f . R.lines'
padLeft, padRight :: Int -> String -> String
padLeft n [] = replicate n ' '
padLeft n (x:xs) = x : padLeft (n1) xs
padRight n = reverse . padLeft n . reverse