bower-json-0.1.0.0: src/Web/BowerJson/Utils.hs
{-# LANGUAGE TupleSections #-}
module Web.BowerJson.Utils where
import Control.Applicative
import Control.Monad
import Control.Category ((>>>))
import Data.List (stripPrefix)
import Data.Map (Map)
import qualified Data.Map as M
import Data.Traversable (traverse)
import Data.Aeson
import qualified Data.Aeson.Types as Aeson
--------------
-- Safe
headMay :: [a] -> Maybe a
headMay [] = Nothing
headMay (x:_) = Just x
lastMay :: [a] -> Maybe a
lastMay [] = Nothing
lastMay [x] = Just x
lastMay (_:xs) = lastMay xs
----------------
-- Aeson
-- | Aeson only provides FromJSON instances such as: @FromJSON a => FromJSON
-- (Map String a)@. This function allows you to parse a Map value from JSON
-- where the keys are not 'String', when you supply a function @(String ->
-- Parser a)@ to parse the keys with.
parseWithArbitraryKeys :: (Ord a, FromJSON v) =>
(String -> Aeson.Parser a) -> Value -> Aeson.Parser (Map a v)
parseWithArbitraryKeys parseKey v' = do
list <- M.toList <$> parseJSON v'
list' <- traverse (\(k, v) -> (,v) <$> parseKey k) list
return (M.fromList list')
-------------------------
-- String manipulation
-- | Given a prefix and a suffix, go through the supplied list, attempting
-- to extract one string from the list which has the given prefix and suffix,
-- All other strings in the list are returned as the second component of the
-- tuple.
takeDelim :: String -> String -> [String] -> (Maybe String, [String])
takeDelim start end = foldr go (Nothing, [])
where
go str (Just x, strs) =
(Just x, str : strs)
go str (Nothing, strs) =
case stripWrapper start end str of
Just str' -> (Just str', strs)
Nothing -> (Nothing, str : strs)
-- | Like stripPrefix, but strips a suffix as well.
stripWrapper :: String -> String -> String -> Maybe String
stripWrapper start end =
stripPrefix start
>>> fmap reverse
>=> stripPrefix (reverse end)
>>> fmap reverse