1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE MultiParamTypeClasses #-}
4 {-# LANGUAGE RankNTypes #-}
5 {-# LANGUAGE UndecidableInstances #-}
7 module Distribution
.FieldGrammar
.FieldDescrs
14 import Distribution
.Compat
.Prelude
17 import Distribution
.Compat
.Lens
(aview
, cloneLens
)
18 import Distribution
.Compat
.Newtype
19 import Distribution
.FieldGrammar
20 import Distribution
.Pretty
(Pretty
(..), showFreeText
)
21 import Distribution
.Utils
.String (trim
)
23 import qualified Data
.Map
as Map
24 import qualified Distribution
.Compat
.CharParsing
as C
25 import qualified Distribution
.Fields
as P
26 import qualified Distribution
.Parsec
as P
27 import qualified Text
.PrettyPrint
as Disp
31 { pPretty
:: !(s
-> Disp
.Doc
)
32 , pParse
:: !(forall m
. P
.CabalParsing m
=> s
-> m s
)
35 -- | A collection of field parsers and pretty-printers.
36 newtype FieldDescrs s a
= F
{runF
:: Map P
.FieldName
(SP s
)}
39 instance Applicative
(FieldDescrs s
) where
41 f
<*> x
= F
(mappend
(runF f
) (runF x
))
43 singletonF
:: P
.FieldName
-> (s
-> Disp
.Doc
) -> (forall m
. P
.CabalParsing m
=> s
-> m s
) -> FieldDescrs s a
44 singletonF fn f g
= F
$ Map
.singleton fn
(SP f g
)
46 -- | Lookup a field value pretty-printer.
47 fieldDescrPretty
:: FieldDescrs s a
-> P
.FieldName
-> Maybe (s
-> Disp
.Doc
)
48 fieldDescrPretty
(F m
) fn
= pPretty
<$> Map
.lookup fn m
50 -- | Lookup a field value parser.
51 fieldDescrParse
:: P
.CabalParsing m
=> FieldDescrs s a
-> P
.FieldName
-> Maybe (s
-> m s
)
52 fieldDescrParse
(F m
) fn
= (\f -> pParse f
) <$> Map
.lookup fn m
57 -> [(P
.FieldName
, s
-> Disp
.Doc
, s
-> m s
)]
58 fieldDescrsToList
= map mk
. Map
.toList
. runF
60 mk
(name
, SP ppr parse
) = (name
, ppr
, parse
)
62 -- | /Note:/ default values are printed.
63 instance FieldGrammar ParsecPretty FieldDescrs
where
64 blurFieldGrammar l
(F m
) = F
(fmap blur m
)
66 blur
(SP f g
) = SP
(f
. aview l
) (cloneLens l g
)
68 booleanFieldDef fn l _def
= singletonF fn f g
70 f s
= Disp
.text
(show (aview l s
))
71 g s
= cloneLens l
(const P
.parsec
) s
73 -- Note: eta expansion is needed for RankNTypes type-checking to work.
75 uniqueFieldAla fn _pack l
= singletonF fn f g
77 f s
= pretty
(pack
' _pack
(aview l s
))
78 g s
= cloneLens l
(const (unpack
' _pack
<$> P
.parsec
)) s
80 optionalFieldAla fn _pack l
= singletonF fn f g
82 f s
= maybe mempty
(pretty
. pack
' _pack
) (aview l s
)
83 g s
= cloneLens l
(const (Just
. unpack
' _pack
<$> P
.parsec
)) s
85 optionalFieldDefAla fn _pack l _def
= singletonF fn f g
87 f s
= pretty
(pack
' _pack
(aview l s
))
88 g s
= cloneLens l
(const (unpack
' _pack
<$> P
.parsec
)) s
90 freeTextField fn l
= singletonF fn f g
92 f s
= maybe mempty showFreeText
(aview l s
)
93 g s
= cloneLens l
(const (Just
<$> parsecFreeText
)) s
95 freeTextFieldDef fn l
= singletonF fn f g
97 f s
= showFreeText
(aview l s
)
98 g s
= cloneLens l
(const parsecFreeText
) s
100 freeTextFieldDefST
= defaultFreeTextFieldDefST
102 monoidalFieldAla fn _pack l
= singletonF fn f g
104 f s
= pretty
(pack
' _pack
(aview l s
))
105 g s
= cloneLens l
(\x
-> mappend x
. unpack
' _pack
<$> P
.parsec
) s
107 prefixedFields _fnPfx _l
= F mempty
108 knownField _
= pure
()
109 deprecatedSince _ _ x
= x
111 availableSince _ _
= id
112 hiddenField _
= F mempty
114 parsecFreeText
:: P
.CabalParsing m
=> m
String
115 parsecFreeText
= dropDotLines
<$ C
.spaces
<*> many C
.anyChar
117 -- Example package with dot lines
118 -- http://hackage.haskell.org/package/copilot-cbmc-0.1/copilot-cbmc.cabal
119 dropDotLines
"." = "."
120 dropDotLines x
= intercalate
"\n" . map dotToEmpty
. lines $ x
122 dotToEmpty x | trim
' x
== "." = ""
123 dotToEmpty x
= trim x
125 trim
' :: String -> String
126 trim
' = dropWhileEnd
(`
elem`
(" \t" :: String))
128 class (P
.Parsec a
, Pretty a
) => ParsecPretty a
129 instance (P
.Parsec a
, Pretty a
) => ParsecPretty a