{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.ModuleName -- Copyright : Duncan Coutts 2008 -- License : BSD3 -- -- Maintainer : cabal-devel@haskell.org -- Portability : portable -- -- Data type for Haskell module names. module Distribution.ModuleName ( ModuleName, fromString, components, toFilePath, main, simple, ) where import Distribution.Text ( Text(..) ) import Distribution.Compat.Binary (Binary) import qualified Data.Char as Char ( isAlphaNum, isUpper ) import Data.Data (Data) import Data.Typeable (Typeable) import qualified Distribution.Compat.ReadP as Parse import qualified Text.PrettyPrint as Disp import Data.List ( intercalate, intersperse ) import GHC.Generics (Generic) import System.FilePath ( pathSeparator ) -- | A valid Haskell module name. -- newtype ModuleName = ModuleName [String] deriving (Eq, Generic, Ord, Read, Show, Typeable, Data) instance Binary ModuleName instance Text ModuleName where disp (ModuleName ms) = Disp.hcat (intersperse (Disp.char '.') (map Disp.text ms)) parse = do ms <- Parse.sepBy1 component (Parse.char '.') return (ModuleName ms) where component = do c <- Parse.satisfy Char.isUpper cs <- Parse.munch validModuleChar return (c:cs) validModuleChar :: Char -> Bool validModuleChar c = Char.isAlphaNum c || c == '_' || c == '\'' validModuleComponent :: String -> Bool validModuleComponent [] = False validModuleComponent (c:cs) = Char.isUpper c && all validModuleChar cs {-# DEPRECATED simple "use ModuleName.fromString instead" #-} simple :: String -> ModuleName simple str = ModuleName [str] -- | Construct a 'ModuleName' from a valid module name 'String'. -- -- This is just a convenience function intended for valid module strings. It is -- an error if it is used with a string that is not a valid module name. If you -- are parsing user input then use 'Distribution.Text.simpleParse' instead. -- fromString :: String -> ModuleName fromString string | all validModuleComponent components' = ModuleName components' | otherwise = error badName where components' = split string badName = "ModuleName.fromString: invalid module name " ++ show string split cs = case break (=='.') cs of (chunk,[]) -> chunk : [] (chunk,_:rest) -> chunk : split rest -- | The module name @Main@. -- main :: ModuleName main = ModuleName ["Main"] -- | The individual components of a hierarchical module name. For example -- -- > components (fromString "A.B.C") = ["A", "B", "C"] -- components :: ModuleName -> [String] components (ModuleName ms) = ms -- | Convert a module name to a file path, but without any file extension. -- For example: -- -- > toFilePath (fromString "A.B.C") = "A/B/C" -- toFilePath :: ModuleName -> FilePath toFilePath = intercalate [pathSeparator] . components