{-# LANGUAGE FlexibleContexts #-} module Elm.Package.Name where import Control.Applicative ((<$>), (<*>)) import Control.Monad.Error import Data.Aeson import Data.Binary import qualified Data.Text as T import qualified Data.Maybe as Maybe import System.FilePath (()) data Name = Name { user :: String , project :: String } deriving (Eq, Ord) dummyName :: Name dummyName = Name "USER" "PROJECT" toString :: Name -> String toString name = user name ++ "/" ++ project name toUrl :: Name -> String toUrl name = user name ++ "/" ++ project name toFilePath :: Name -> FilePath toFilePath name = user name project name fromString :: String -> Maybe Name fromString string = case break (=='/') string of ( user@(_:_), '/' : project@(_:_) ) | all (/='/') project -> Just (Name user project) _ -> Nothing fromString' :: (MonadError String m) => String -> m Name fromString' string = Maybe.maybe (throwError $ errorMsg string) return (fromString string) instance Binary Name where get = Name <$> get <*> get put (Name user project) = do put user put project instance FromJSON Name where parseJSON (String text) = let string = T.unpack text in Maybe.maybe (fail $ errorMsg string) return (fromString string) parseJSON _ = fail "Project name must be a string." instance ToJSON Name where toJSON name = toJSON (toString name) errorMsg :: String -> String errorMsg string = unlines [ "Dependency file has an invalid name: " ++ string , "Must have format USER/PROJECT and match a public github project." ]