module Distribution.ModuleName (
ModuleName,
fromString,
fromComponents,
components,
toFilePath,
main,
validModuleComponent,
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Parsec
import Distribution.Pretty
import Distribution.Utils.ShortText (ShortText, fromShortText, toShortText)
import System.FilePath (pathSeparator)
import qualified Distribution.Compat.CharParsing as P
import qualified Distribution.Compat.DList as DList
import qualified Text.PrettyPrint as Disp
newtype ModuleName = ModuleName ShortText
deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)
unModuleName :: ModuleName -> String
unModuleName (ModuleName s) = fromShortText s
instance Binary ModuleName
instance Structured ModuleName
instance NFData ModuleName where
rnf (ModuleName ms) = rnf ms
instance Pretty ModuleName where
pretty = Disp.text . unModuleName
instance Parsec ModuleName where
parsec = parsecModuleName
parsecModuleName :: forall m. CabalParsing m => m ModuleName
parsecModuleName = state0 DList.empty where
upper :: m Char
!upper = P.satisfy isUpper
ch :: m Char
!ch = P.satisfy (\c -> validModuleChar c || c == '.')
alt :: m ModuleName -> m ModuleName -> m ModuleName
!alt = (<|>)
state0 :: DList.DList Char -> m ModuleName
state0 acc = do
c <- upper
state1 (DList.snoc acc c)
state1 :: DList.DList Char -> m ModuleName
state1 acc = state1' acc `alt` return (fromString (DList.toList acc))
state1' :: DList.DList Char -> m ModuleName
state1' acc = do
c <- ch
case c of
'.' -> state0 (DList.snoc acc c)
_ -> state1 (DList.snoc acc c)
validModuleChar :: Char -> Bool
validModuleChar c = isAlphaNum c || c == '_' || c == '\''
validModuleComponent :: String -> Bool
validModuleComponent [] = False
validModuleComponent (c:cs) = isUpper c && all validModuleChar cs
instance IsString ModuleName where
fromString = ModuleName . toShortText
fromComponents :: [String] -> ModuleName
fromComponents comps = fromString (intercalate "." comps)
main :: ModuleName
main = ModuleName (fromString "Main")
components :: ModuleName -> [String]
components mn = split (unModuleName mn)
where
split cs = case break (=='.') cs of
(chunk,[]) -> chunk : []
(chunk,_:rest) -> chunk : split rest
toFilePath :: ModuleName -> FilePath
toFilePath = map f . unModuleName where
f '.' = pathSeparator
f c = c