{-# LANGUAGE FlexibleContexts #-}
module Hakyll.Core.Util.String
( trim
, replaceAll
, splitAll
, needlePrefix
, removeWinPathSeparator
) where
import Data.Char (isSpace)
import Data.List (isPrefixOf)
import Data.Maybe (listToMaybe)
import Text.Regex.TDFA ((=~~))
trim :: String -> String
trim :: String -> String
trim = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
trim' (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
trim'
where
trim' :: String -> String
trim' = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace
replaceAll :: String
-> (String -> String)
-> String
-> String
replaceAll :: String -> (String -> String) -> String -> String
replaceAll String
pattern String -> String
f String
source = String -> String
replaceAll' String
source
where
replaceAll' :: String -> String
replaceAll' String
src = case [(Int, Int)] -> Maybe (Int, Int)
forall a. [a] -> Maybe a
listToMaybe (String
src String -> String -> [(Int, Int)]
forall source source1 target (m :: * -> *).
(RegexMaker Regex CompOption ExecOption source,
RegexContext Regex source1 target, MonadFail m) =>
source1 -> source -> m target
=~~ String
pattern) of
Maybe (Int, Int)
Nothing -> String
src
Just (Int
o, Int
l) ->
let (String
before, String
tmp) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
o String
src
(String
capture, String
after) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
l String
tmp
in String
before String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
f String
capture String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
replaceAll' String
after
splitAll :: String
-> String
-> [String]
splitAll :: String -> String -> [String]
splitAll String
pattern = (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
forall a. RegexLike Regex [a] => [a] -> [[a]]
splitAll'
where
splitAll' :: [a] -> [[a]]
splitAll' [a]
src = case [(Int, Int)] -> Maybe (Int, Int)
forall a. [a] -> Maybe a
listToMaybe ([a]
src [a] -> String -> [(Int, Int)]
forall source source1 target (m :: * -> *).
(RegexMaker Regex CompOption ExecOption source,
RegexContext Regex source1 target, MonadFail m) =>
source1 -> source -> m target
=~~ String
pattern) of
Maybe (Int, Int)
Nothing -> [[a]
src]
Just (Int
o, Int
l) ->
let ([a]
before, [a]
tmp) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
o [a]
src
in [a]
before [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [a] -> [[a]]
splitAll' (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
l [a]
tmp)
needlePrefix :: String -> String -> Maybe String
needlePrefix :: String -> String -> Maybe String
needlePrefix String
needle String
haystack = String -> String -> Maybe String
go [] String
haystack
where
go :: String -> String -> Maybe String
go String
_ [] = Maybe String
forall a. Maybe a
Nothing
go String
acc xss :: String
xss@(Char
x:String
xs)
| String
needle String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
xss = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. [a] -> [a]
reverse String
acc
| Bool
otherwise = String -> String -> Maybe String
go (Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String
acc) String
xs
removeWinPathSeparator :: String -> String
removeWinPathSeparator :: String -> String
removeWinPathSeparator = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Char
c -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\\' then [Char
'/'] else [Char
c])