@@ -18,10 +18,14 @@ module Distribution.FieldGrammar.Newtypes (
18
18
Sep (.. ),
19
19
-- ** Type
20
20
List ,
21
- -- * Set
21
+ -- ** Set
22
22
alaSet ,
23
23
alaSet' ,
24
24
Set' ,
25
+ -- ** NonEmpty
26
+ alaNonEmpty ,
27
+ alaNonEmpty' ,
28
+ NonEmpty' ,
25
29
-- * Version & License
26
30
SpecVersion (.. ),
27
31
TestedWith (.. ),
@@ -46,6 +50,7 @@ import Distribution.Version
46
50
(LowerBound (.. ), Version , VersionRange , VersionRangeF (.. ), anyVersion , asVersionIntervals , cataVersionRange , mkVersion , version0 , versionNumbers )
47
51
import Text.PrettyPrint (Doc , comma , fsep , punctuate , text , vcat )
48
52
53
+ import qualified Data.List.NonEmpty as NE
49
54
import qualified Data.Set as Set
50
55
import qualified Distribution.Compat.CharParsing as P
51
56
import qualified Distribution.SPDX as SPDX
@@ -68,31 +73,41 @@ data NoCommaFSep = NoCommaFSep
68
73
class Sep sep where
69
74
prettySep :: Proxy sep -> [Doc ] -> Doc
70
75
71
- parseSep :: CabalParsing m => Proxy sep -> m a -> m [a ]
76
+ parseSep :: CabalParsing m => Proxy sep -> m a -> m [a ]
77
+ parseSepNE :: CabalParsing m => Proxy sep -> m a -> m (NonEmpty a )
72
78
73
79
instance Sep CommaVCat where
74
80
prettySep _ = vcat . punctuate comma
75
81
parseSep _ p = do
76
82
v <- askCabalSpecVersion
77
83
if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p
84
+ parseSepNE _ p = do
85
+ v <- askCabalSpecVersion
86
+ if v >= CabalSpecV2_2 then parsecLeadingCommaNonEmpty p else parsecCommaNonEmpty p
78
87
instance Sep CommaFSep where
79
88
prettySep _ = fsep . punctuate comma
80
89
parseSep _ p = do
81
90
v <- askCabalSpecVersion
82
91
if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p
92
+ parseSepNE _ p = do
93
+ v <- askCabalSpecVersion
94
+ if v >= CabalSpecV2_2 then parsecLeadingCommaNonEmpty p else parsecCommaNonEmpty p
83
95
instance Sep VCat where
84
96
prettySep _ = vcat
85
97
parseSep _ p = do
86
98
v <- askCabalSpecVersion
87
99
if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p
100
+ parseSepNE _ p = NE. some1 (p <* P. spaces)
88
101
instance Sep FSep where
89
102
prettySep _ = fsep
90
103
parseSep _ p = do
91
104
v <- askCabalSpecVersion
92
105
if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p
106
+ parseSepNE _ p = NE. some1 (p <* P. spaces)
93
107
instance Sep NoCommaFSep where
94
- prettySep _ = fsep
95
- parseSep _ p = many (p <* P. spaces)
108
+ prettySep _ = fsep
109
+ parseSep _ p = many (p <* P. spaces)
110
+ parseSepNE _ p = NE. some1 (p <* P. spaces)
96
111
97
112
-- | List separated with optional commas. Displayed with @sep@, arguments of
98
113
-- type @a@ are parsed and pretty-printed as @b@.
@@ -158,6 +173,39 @@ instance (Newtype a b, Ord a, Sep sep, Parsec b) => Parsec (Set' sep b a) where
158
173
instance (Newtype a b , Sep sep , Pretty b ) => Pretty (Set' sep b a ) where
159
174
pretty = prettySep (Proxy :: Proxy sep ) . map (pretty . (pack :: a -> b )) . Set. toList . unpack
160
175
176
+ --
177
+ -- | Like 'List', but for 'NonEmpty'.
178
+ --
179
+ -- @since 3.2.0.0
180
+ newtype NonEmpty' sep b a = NonEmpty' { _getNonEmpty :: NonEmpty a }
181
+
182
+ -- | 'alaNonEmpty' and 'alaNonEmpty'' are simply 'NonEmpty'' constructor, with additional phantom
183
+ -- arguments to constrain the resulting type
184
+ --
185
+ -- >>> :t alaNonEmpty VCat
186
+ -- alaNonEmpty VCat :: NonEmpty a -> NonEmpty' VCat (Identity a) a
187
+ --
188
+ -- >>> unpack' (alaNonEmpty' FSep Token) <$> eitherParsec "foo bar foo"
189
+ -- Right ("foo" :| ["bar","foo"])
190
+ --
191
+ -- @since 3.2.0.0
192
+ alaNonEmpty :: sep -> NonEmpty a -> NonEmpty' sep (Identity a ) a
193
+ alaNonEmpty _ = NonEmpty'
194
+
195
+ -- | More general version of 'alaNonEmpty'.
196
+ --
197
+ -- @since 3.2.0.0
198
+ alaNonEmpty' :: sep -> (a -> b ) -> NonEmpty a -> NonEmpty' sep b a
199
+ alaNonEmpty' _ _ = NonEmpty'
200
+
201
+ instance Newtype (NonEmpty a ) (NonEmpty' sep wrapper a )
202
+
203
+ instance (Newtype a b , Sep sep , Parsec b ) => Parsec (NonEmpty' sep b a ) where
204
+ parsec = pack . fmap (unpack :: b -> a ) <$> parseSepNE (Proxy :: Proxy sep ) parsec
205
+
206
+ instance (Newtype a b , Sep sep , Pretty b ) => Pretty (NonEmpty' sep b a ) where
207
+ pretty = prettySep (Proxy :: Proxy sep ) . map (pretty . (pack :: a -> b )) . NE. toList . unpack
208
+
161
209
-------------------------------------------------------------------------------
162
210
-- Identifiers
163
211
-------------------------------------------------------------------------------
0 commit comments