1{-# LANGUAGE DeriveFunctor #-}
2{-# LANGUAGE DeriveFoldable #-}
3{-# LANGUAGE DeriveTraversable #-}
4-- | Cabal-like file AST types: 'Field', 'Section' etc
5--
6-- These types are parametrized by an annotation.
7module Distribution.Fields.Field (
8    -- * Cabal file
9    Field (..),
10    fieldName,
11    fieldAnn,
12    fieldUniverse,
13    FieldLine (..),
14    fieldLineAnn,
15    fieldLineBS,
16    SectionArg (..),
17    sectionArgAnn,
18    -- * Name
19    FieldName,
20    Name (..),
21    mkName,
22    getName,
23    nameAnn,
24    ) where
25
26import           Prelude ()
27import           Distribution.Compat.Prelude
28import           Data.ByteString             (ByteString)
29import qualified Data.ByteString.Char8       as B
30import qualified Data.Char                   as Char
31
32-------------------------------------------------------------------------------
33-- Cabal file
34-------------------------------------------------------------------------------
35
36-- | A Cabal-like file consists of a series of fields (@foo: bar@) and sections (@library ...@).
37data Field ann
38    = Field   !(Name ann) [FieldLine ann]
39    | Section !(Name ann) [SectionArg ann] [Field ann]
40  deriving (Eq, Show, Functor, Foldable, Traversable)
41
42-- | Section of field name
43fieldName :: Field ann -> Name ann
44fieldName (Field n _ )    = n
45fieldName (Section n _ _) = n
46
47fieldAnn :: Field ann -> ann
48fieldAnn = nameAnn . fieldName
49
50-- | All transitive descendants of 'Field', including itself.
51--
52-- /Note:/ the resulting list is never empty.
53--
54fieldUniverse :: Field ann -> [Field ann]
55fieldUniverse f@(Section _ _ fs) = f : concatMap fieldUniverse fs
56fieldUniverse f@(Field _ _)      = [f]
57
58-- | A line of text representing the value of a field from a Cabal file.
59-- A field may contain multiple lines.
60--
61-- /Invariant:/ 'ByteString' has no newlines.
62data FieldLine ann  = FieldLine  !ann !ByteString
63  deriving (Eq, Show, Functor, Foldable, Traversable)
64
65-- | @since 3.0.0.0
66fieldLineAnn :: FieldLine ann -> ann
67fieldLineAnn (FieldLine ann _) = ann
68
69-- | @since 3.0.0.0
70fieldLineBS :: FieldLine ann -> ByteString
71fieldLineBS (FieldLine _ bs) = bs
72
73-- | Section arguments, e.g. name of the library
74data SectionArg ann
75    = SecArgName  !ann !ByteString
76      -- ^ identifier, or something which looks like number. Also many dot numbers, i.e. "7.6.3"
77    | SecArgStr   !ann !ByteString
78      -- ^ quoted string
79    | SecArgOther !ann !ByteString
80      -- ^ everything else, mm. operators (e.g. in if-section conditionals)
81  deriving (Eq, Show, Functor, Foldable, Traversable)
82
83-- | Extract annotation from 'SectionArg'.
84sectionArgAnn :: SectionArg ann -> ann
85sectionArgAnn (SecArgName ann _)  = ann
86sectionArgAnn (SecArgStr ann _)   = ann
87sectionArgAnn (SecArgOther ann _) = ann
88
89-------------------------------------------------------------------------------
90-- Name
91-------------------------------------------------------------------------------
92
93type FieldName = ByteString
94
95-- | A field name.
96--
97-- /Invariant/: 'ByteString' is lower-case ASCII.
98data Name ann  = Name       !ann !FieldName
99  deriving (Eq, Show, Functor, Foldable, Traversable)
100
101mkName :: ann -> FieldName -> Name ann
102mkName ann bs = Name ann (B.map Char.toLower bs)
103
104getName :: Name ann -> FieldName
105getName (Name _ bs) = bs
106
107nameAnn :: Name ann -> ann
108nameAnn (Name ann _) = ann
109