yaml 0.8.12 → 0.8.13
raw patch · 7 files changed
+161/−18 lines, 7 filesdep ~aeson
Dependency ranges changed: aeson
Files
- ChangeLog.md +4/−0
- Data/Yaml.hs +0/−16
- Data/Yaml/Builder.hs +51/−1
- Data/Yaml/Internal.hs +19/−0
- Data/Yaml/Pretty.hs +58/−0
- test/Data/YamlSpec.hs +27/−0
- yaml.cabal +2/−1
ChangeLog.md view
@@ -1,3 +1,7 @@+## 0.8.13++* Pretty module [#66](https://github.com/snoyberg/yaml/pull/66)+ ## 0.8.12 * Proper handling of `String "+123"` [#64](https://github.com/snoyberg/yaml/issues/64)
Data/Yaml.hs view
@@ -144,22 +144,6 @@ EventScalar (encodeUtf8 k) StrTag PlainNoTag Nothing : objToEvents' v rest --- | Strings which must be escaped so as not to be treated as non-string scalars.-specialStrings :: HashSet.HashSet Text-specialStrings = HashSet.fromList $ T.words- "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 ~"--isNumeric :: Text -> Bool-isNumeric =- T.all isNumeric'- where- isNumeric' c = ('0' <= c && c <= '9')- || c == 'e'- || c == 'E'- || c == '.'- || c == '-'- || c == '+'- decode :: FromJSON a => ByteString -> Maybe a
Data/Yaml/Builder.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-} -- | NOTE: This module is a highly experimental preview release. It may change -- drastically, or be entirely removed, in a future release. module Data.Yaml.Builder@@ -7,6 +9,10 @@ , mapping , array , string+ , bool+ , null+ , scientific+ , number , toByteString , writeYamlFile , (.=)@@ -15,12 +21,26 @@ import Data.Conduit import Data.ByteString (ByteString) import Text.Libyaml+import Data.Yaml.Internal import Data.Text (Text)+import Data.Scientific (Scientific)+import Data.Aeson.Types (Value(..))+import qualified Data.HashSet as HashSet+import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) import System.IO.Unsafe (unsafePerformIO) import Control.Arrow (second) import qualified Data.ByteString.Char8 as S8 import Control.Monad.Trans.Resource (runResourceT)+#if MIN_VERSION_aeson(0, 7, 0)+import qualified Data.Text.Encoding as TE+import qualified Data.Text.Lazy as TL+import Data.Text.Lazy.Builder (toLazyText)+import Data.Aeson.Encode (encodeToTextBuilder)+#else+import qualified Data.ByteString.Char8 as S8+#endif+import Prelude hiding (null) (.=) :: ToYaml a => Text -> a -> (Text, YamlBuilder) k .= v = (k, toYaml v)@@ -55,7 +75,37 @@ go (YamlBuilder b) rest = b rest string :: Text -> YamlBuilder-string t = YamlBuilder (EventScalar (encodeUtf8 t) StrTag PlainNoTag Nothing:)+-- Empty strings need special handling to ensure they get quoted. This avoids:+-- https://github.com/snoyberg/yaml/issues/24+string "" = YamlBuilder (EventScalar "" NoTag SingleQuoted Nothing :)+string s =+ YamlBuilder (event :)+ where+ event+ -- Make sure that special strings are encoded as strings properly.+ -- See: https://github.com/snoyberg/yaml/issues/31+ | s `HashSet.member` specialStrings || isNumeric s = EventScalar (encodeUtf8 s) NoTag SingleQuoted Nothing+ | otherwise = EventScalar (encodeUtf8 s) StrTag PlainNoTag Nothing+ +-- Use aeson's implementation which gets rid of annoying decimal points+scientific :: Scientific -> YamlBuilder+scientific n = YamlBuilder (EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder (Number n)) IntTag PlainNoTag Nothing :)++{-# DEPRECATED number "Use scientific" #-}+#if MIN_VERSION_aeson(0,7,0)+number :: Scientific -> YamlBuilder+number = scientific+#else+number :: Number -> YamlBuilder+number n rest = YamlBuilder (EventScalar (S8.pack $ show n) IntTag PlainNoTag Nothing :)+#endif++bool :: Bool -> YamlBuilder+bool True = YamlBuilder (EventScalar "true" BoolTag PlainNoTag Nothing :)+bool False = YamlBuilder (EventScalar "false" BoolTag PlainNoTag Nothing :)++null :: YamlBuilder+null = YamlBuilder (EventScalar "null" NullTag PlainNoTag Nothing :) toEvents :: YamlBuilder -> [Event] toEvents (YamlBuilder front) =
Data/Yaml/Internal.hs view
@@ -9,6 +9,8 @@ , parse , decodeHelper , decodeHelper_+ , specialStrings+ , isNumeric ) where import qualified Text.Libyaml as Y@@ -41,6 +43,7 @@ import Data.Attoparsec.Number #endif import Control.Monad.Trans.Resource (ResourceT, runResourceT)+import qualified Data.HashSet as HashSet data ParseException = NonScalarKey | UnknownAlias { _anchorName :: Y.AnchorName }@@ -257,3 +260,19 @@ (Left . AesonException) Right (parseEither parseJSON y)++-- | Strings which must be escaped so as not to be treated as non-string scalars.+specialStrings :: HashSet.HashSet Text+specialStrings = HashSet.fromList $ T.words+ "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 ~"++isNumeric :: Text -> Bool+isNumeric =+ T.all isNumeric'+ where+ isNumeric' c = ('0' <= c && c <= '9')+ || c == 'e'+ || c == 'E'+ || c == '.'+ || c == '-'+ || c == '+'
+ Data/Yaml/Pretty.hs view
@@ -0,0 +1,58 @@+-- | Prettier YAML encoding.+--+-- Since 0.8.13+module Data.Yaml.Pretty+ ( encodePretty+ , Config+ , getConfCompare+ , setConfCompare+ , defConfig+ ) where++import Data.Yaml.Builder+import Data.Aeson.Types+import Data.Text (Text)+import Data.Monoid+import qualified Data.Vector as V+import qualified Data.HashMap.Strict as HM+import Data.Function (on)+import Data.List (sortBy)+import Data.ByteString (ByteString)+import Prelude hiding (null)++-- |+-- Since 0.8.13+data Config = Config+ { confCompare :: Text -> Text -> Ordering -- ^ Function used to sort keys in objects+ }++-- | The default configuration: do not sort objects.+--+-- Since 0.8.13+defConfig :: Config+defConfig = Config mempty++-- |+-- Since 0.8.13+getConfCompare :: Config -> Text -> Text -> Ordering+getConfCompare = confCompare++-- |+-- Since 0.8.13+setConfCompare :: (Text -> Text -> Ordering) -> Config -> Config+setConfCompare cmp c = c { confCompare = cmp }++pretty :: Config -> Value -> YamlBuilder+pretty cfg = go+ where go (Object o) = mapping (sortBy (confCompare cfg `on` fst) $ HM.toList $ HM.map go o)+ go (Array a) = array (fmap go $ V.toList a)+ go Null = null+ go (String s) = string s+ go (Number n) = number n+ go (Bool b) = bool b++-- | Configurable 'encode'.+--+-- Since 0.8.13+encodePretty :: ToJSON a => Config -> a -> ByteString+encodePretty cfg = toByteString . pretty cfg . toJSON
test/Data/YamlSpec.hs view
@@ -22,6 +22,7 @@ import Test.Mockery.Directory import qualified Data.Yaml as D+import qualified Data.Yaml.Pretty as Pretty import Data.Yaml (object, array, (.=)) import Data.Maybe import qualified Data.HashMap.Strict as M@@ -65,6 +66,10 @@ it "encode/decode strings" caseEncodeDecodeStrings it "decode invalid file" caseDecodeInvalid it "processes datatypes" caseDataTypes+ describe "Data.Yaml.Pretty" $ do+ it "encode/decode" caseEncodeDecodeDataPretty+ it "encode/decode strings" caseEncodeDecodeStringsPretty+ it "processes datatypes" caseDataTypesPretty describe "Data.Yaml aliases" $ do it "simple scalar alias" caseSimpleScalarAlias it "simple sequence alias" caseSimpleSequenceAlias@@ -299,6 +304,11 @@ let out = D.decode $ D.encode sample out @?= Just sample +caseEncodeDecodeDataPretty :: Assertion+caseEncodeDecodeDataPretty = do+ let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample+ out @?= Just sample+ caseEncodeDecodeFileData :: Assertion caseEncodeDecodeFileData = withFile "" $ \fp -> do D.encodeFile fp sample@@ -310,6 +320,11 @@ let out = D.decode $ D.encode sample out @?= Just sample +caseEncodeDecodeStringsPretty :: Assertion+caseEncodeDecodeStringsPretty = do+ let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample+ out @?= Just sample+ caseDecodeInvalid :: Assertion caseDecodeInvalid = do let invalid = B8.pack "\tthis is 'not' valid :-)"@@ -391,6 +406,18 @@ , ("null", D.Null) ] +caseDataTypesPretty :: Assertion+caseDataTypesPretty =+ D.decode (Pretty.encodePretty Pretty.defConfig val) @?= Just val+ where+ val = object+ [ ("string", D.String "foo")+ , ("int", D.Number 5)+ , ("float", D.Number 4.3)+ , ("true", D.Bool True)+ , ("false", D.Bool False)+ , ("null", D.Null)+ ] caseQuotedNumber, caseUnquotedNumber, caseAttribNumber, caseIntegerDecimals :: Assertion caseQuotedNumber = D.decode "foo: \"1234\"" @?= Just (object [("foo", D.String "1234")]) caseUnquotedNumber = D.decode "foo: 1234" @?= Just (object [("foo", D.Number 1234)])
yaml.cabal view
@@ -1,5 +1,5 @@ name: yaml-version: 0.8.12+version: 0.8.13 license: BSD3 license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov @@ -57,6 +57,7 @@ Data.Yaml Data.Yaml.Aeson Data.Yaml.Builder+ Data.Yaml.Pretty Data.Yaml.Parser Data.Yaml.Include other-modules: