on master help sign in
Implement some additional functions in Builder
7df7469Oleg Grenrus
Data/Yaml.hs−16
@@ -144,22 +144,6 @@ pairToEvents (k, v) rest =
144 EventScalar (encodeUtf8 k) StrTag PlainNoTag Nothing
144 EventScalar (encodeUtf8 k) StrTag PlainNoTag Nothing
145 : objToEvents' v rest
145 : objToEvents' v rest
146
146
147−-- | Strings which must be escaped so as not to be treated as non-string scalars.
148−specialStrings :: HashSet.HashSet Text
149−specialStrings = HashSet.fromList $ T.words
150− "y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~"
151−
152−isNumeric :: Text -> Bool
153−isNumeric =
154− T.all isNumeric'
155− where
156− isNumeric' c = ('0' <= c && c <= '9')
157− || c == 'e'
158− || c == 'E'
159− || c == '.'
160− || c == '-'
161− || c == '+'
162−
163decode :: FromJSON a
147decode :: FromJSON a
164 => ByteString
148 => ByteString
165 -> Maybe a
149 -> Maybe a
Data/Yaml/Builder.hs+67−1
@@ -1,4 +1,6 @@
1{-# LANGUAGE FlexibleInstances #-}
1{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE CPP #-}
2-- | NOTE: This module is a highly experimental preview release. It may change
4-- | NOTE: This module is a highly experimental preview release. It may change
3-- drastically, or be entirely removed, in a future release.
5-- drastically, or be entirely removed, in a future release.
4module Data.Yaml.Builder
6module Data.Yaml.Builder
@@ -7,6 +9,10 @@ module Data.Yaml.Builder
7 , mapping
9 , mapping
8 , array
10 , array
9 , string
11 , string
12+ , bool
13+ , null
14+ , scientific
15+ , number
10 , toByteString
16 , toByteString
11 , writeYamlFile
17 , writeYamlFile
12 , (.=)
18 , (.=)
@@ -16,11 +22,24 @@ import Data.Conduit
16import Data.ByteString (ByteString)
22import Data.ByteString (ByteString)
17import Text.Libyaml
23import Text.Libyaml
18import Data.Text (Text)
24import Data.Text (Text)
25+import Data.Scientific (Scientific)
26+import Data.Aeson.Types (Value(..))
27+import qualified Data.HashSet as HashSet
28+import qualified Data.Text as T
19import Data.Text.Encoding (encodeUtf8)
29import Data.Text.Encoding (encodeUtf8)
20import System.IO.Unsafe (unsafePerformIO)
30import System.IO.Unsafe (unsafePerformIO)
21import Control.Arrow (second)
31import Control.Arrow (second)
22import qualified Data.ByteString.Char8 as S8
32import qualified Data.ByteString.Char8 as S8
23import Control.Monad.Trans.Resource (runResourceT)
33import Control.Monad.Trans.Resource (runResourceT)
34+#if MIN_VERSION_aeson(0, 7, 0)
35+import qualified Data.Text.Encoding as TE
36+import qualified Data.Text.Lazy as TL
37+import Data.Text.Lazy.Builder (toLazyText)
38+import Data.Aeson.Encode (encodeToTextBuilder)
39+#else
40+import qualified Data.ByteString.Char8 as S8
41+#endif
42+import Prelude hiding (null)
24
43
25(.=) :: ToYaml a => Text -> a -> (Text, YamlBuilder)
44(.=) :: ToYaml a => Text -> a -> (Text, YamlBuilder)
26k .= v = (k, toYaml v)
45k .= v = (k, toYaml v)
@@ -55,7 +74,54 @@ array bs =
55 go (YamlBuilder b) rest = b rest
74 go (YamlBuilder b) rest = b rest
56
75
57string :: Text -> YamlBuilder
76string :: Text -> YamlBuilder
77+-- Empty strings need special handling to ensure they get quoted. This avoids:
78+-- https://github.com/snoyberg/yaml/issues/24
79+string "" = YamlBuilder (EventScalar "" NoTag SingleQuoted Nothing :)
80+string s =
81+ YamlBuilder (event :)
82+ where
83+ event
84+ -- Make sure that special strings are encoded as strings properly.
85+ -- See: https://github.com/snoyberg/yaml/issues/31
86+ | s `HashSet.member` specialStrings || isNumeric s = EventScalar (encodeUtf8 s) NoTag SingleQuoted Nothing
58−string t = YamlBuilder (EventScalar (encodeUtf8 t) StrTag PlainNoTag Nothing:)
87+ | otherwise = EventScalar (encodeUtf8 s) StrTag PlainNoTag Nothing
88+
89+ -- | Strings which must be escaped so as not to be treated as non-string scalars.
90+ specialStrings :: HashSet.HashSet Text
91+ specialStrings = HashSet.fromList $ T.words
92+ "y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~"
93+
94+ isNumeric :: Text -> Bool
95+ isNumeric =
96+ T.all isNumeric'
97+ where
98+ isNumeric' c = ('0' <= c && c <= '9')
99+ || c == 'e'
100+ || c == 'E'
101+ || c == '.'
102+ || c == '-'
103+ || c == '+'
104+
105+
106+-- Use aeson's implementation which gets rid of annoying decimal points
107+scientific :: Scientific -> YamlBuilder
108+scientific n = YamlBuilder (EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder (Number n)) IntTag PlainNoTag Nothing :)
109+
110+{-# DEPRECATED number "Use scientific" #-}
111+#if MIN_VERSION_aeson(0,7,0)
112+number :: Scientific -> YamlBuilder
113+number = scientific
114+#else
115+number :: Number -> YamlBuilder
116+number n rest = YamlBuilder (EventScalar (S8.pack $ show n) IntTag PlainNoTag Nothing :)
117+#endif
118+
119+bool :: Bool -> YamlBuilder
120+bool True = YamlBuilder (EventScalar "true" BoolTag PlainNoTag Nothing :)
121+bool False = YamlBuilder (EventScalar "false" BoolTag PlainNoTag Nothing :)
122+
123+null :: YamlBuilder
124+null = YamlBuilder (EventScalar "null" NullTag PlainNoTag Nothing :)
59
125
60toEvents :: YamlBuilder -> [Event]
126toEvents :: YamlBuilder -> [Event]
61toEvents (YamlBuilder front) =
127toEvents (YamlBuilder front) =
Data/Yaml/Internal.hs+19
@@ -9,6 +9,8 @@ module Data.Yaml.Internal
9 , parse
9 , parse
10 , decodeHelper
10 , decodeHelper
11 , decodeHelper_
11 , decodeHelper_
12+ , specialStrings
13+ , isNumeric
12 ) where
14 ) where
13
15
14import qualified Text.Libyaml as Y
16import qualified Text.Libyaml as Y
@@ -41,6 +43,7 @@ import Data.Scientific (fromFloatDigits)
41import Data.Attoparsec.Number
43import Data.Attoparsec.Number
42#endif
44#endif
43import Control.Monad.Trans.Resource (ResourceT, runResourceT)
45import Control.Monad.Trans.Resource (ResourceT, runResourceT)
46+import qualified Data.HashSet as HashSet
44
47
45data ParseException = NonScalarKey
48data ParseException = NonScalarKey
46 | UnknownAlias { _anchorName :: Y.AnchorName }
49 | UnknownAlias { _anchorName :: Y.AnchorName }
@@ -257,3 +260,19 @@ decodeHelper_ src = do
257 (Left . AesonException)
260 (Left . AesonException)
258 Right
261 Right
259 (parseEither parseJSON y)
262 (parseEither parseJSON y)
263+
264+-- | Strings which must be escaped so as not to be treated as non-string scalars.
265+specialStrings :: HashSet.HashSet Text
266+specialStrings = HashSet.fromList $ T.words
267+ "y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~"
268+
269+isNumeric :: Text -> Bool
270+isNumeric =
271+ T.all isNumeric'
272+ where
273+ isNumeric' c = ('0' <= c && c <= '9')
274+ || c == 'e'
275+ || c == 'E'
276+ || c == '.'
277+ || c == '-'
278+ || c == '+'