yaml 0.10.1.1 → 0.10.2.0
raw patch · 5 files changed
+196/−59 lines, 5 files
Files
- ChangeLog.md +5/−0
- src/Data/Yaml.hs +110/−38
- src/Data/Yaml/Builder.hs +16/−2
- src/Text/Libyaml.hs +52/−6
- yaml.cabal +13/−13
ChangeLog.md view
@@ -1,5 +1,10 @@ # ChangeLog for yaml +## 0.10.2.0++* Add `EncodeOptions` and `FormatOptions` to control the style of the encoded YAML. [#153](https://github.com/snoyberg/yaml/pull/153)+* Default to using literal style for multiline strings [#152](https://github.com/snoyberg/yaml/issues/152)+ ## 0.10.1.1 * Correctly declare libyaml dependency on system-libyaml flag [#151](https://github.com/snoyberg/yaml/pull/151)
src/Data/Yaml.hs view
@@ -28,7 +28,9 @@ #endif ( -- * Encoding encode+ , encodeWith , encodeFile+ , encodeFileWith -- * Decoding , decodeEither' , decodeFileEither@@ -66,6 +68,15 @@ -- * Classes , ToJSON (..) , FromJSON (..)+ -- * Custom encoding+ , isSpecialString+ , EncodeOptions+ , defaultEncodeOptions+ , setStringStyle+ , setFormat+ , FormatOptions+ , defaultFormatOptions+ , setWidth -- * Deprecated , decode , decodeFile@@ -95,70 +106,131 @@ import qualified Data.HashMap.Strict as M import qualified Data.HashSet as HashSet import Data.Text.Encoding (encodeUtf8)+import qualified Data.Text as T import qualified Data.Text.Encoding as TE import qualified Data.Text.Lazy as TL import Data.Text.Lazy.Builder (toLazyText) import qualified Data.Vector as V import System.IO.Unsafe (unsafePerformIO)+import Data.Text (Text) import Data.Yaml.Internal-import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile)+import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile, encodeWith, encodeFileWith) import qualified Text.Libyaml as Y +-- |+-- @since 0.10.2.0+data EncodeOptions = EncodeOptions+ { encodeOptionsStringStyle :: Text -> ( Tag, Style )+ , encodeOptionsFormat :: FormatOptions+ }++-- | Set the string style in the encoded YAML. This is a function that decides+-- for each string the type of YAML string to output.+--+-- __WARNING__: You must ensure that special strings (like @"yes"@\/@"no"@\/@"null"@\/@"1234"@) are not encoded with the 'Plain' style, because+-- then they will be decoded as boolean, null or numeric values. You can use 'isSpecialString' to detect them.+--+-- By default, strings are encoded as follows:+--+-- * Any string containing a newline character uses the 'Literal' style+--+-- * Otherwise, any special string (see 'isSpecialString') uses 'SingleQuoted'+--+-- * Otherwise, use 'Plain'+--+-- @since 0.10.2.0+setStringStyle :: (Text -> ( Tag, Style )) -> EncodeOptions -> EncodeOptions+setStringStyle s opts = opts { encodeOptionsStringStyle = s }++-- | Set the encoding formatting for the encoded YAML. By default, this is `defaultFormatOptions`.+--+-- @since 0.10.2.0+setFormat :: FormatOptions -> EncodeOptions -> EncodeOptions+setFormat f opts = opts { encodeOptionsFormat = f }++-- | Determine whether a string must be quoted in YAML and can't appear as plain text.+-- Useful if you want to use 'setStringStyle'.+--+-- @since 0.10.2.0+isSpecialString :: Text -> Bool+isSpecialString s = s `HashSet.member` specialStrings || isNumeric s++-- |+-- @since 0.10.2.0+defaultEncodeOptions :: EncodeOptions+defaultEncodeOptions = EncodeOptions+ { encodeOptionsStringStyle = \s ->+ -- Empty strings need special handling to ensure they get quoted. This avoids:+ -- https://github.com/snoyberg/yaml/issues/24+ case () of+ ()+ | "\n" `T.isInfixOf` s -> ( NoTag, Literal )+ | isSpecialString s -> ( NoTag, SingleQuoted )+ | otherwise -> ( StrTag, PlainNoTag )+ , encodeOptionsFormat = defaultFormatOptions+ }+ -- | Encode a value into its YAML representation. encode :: ToJSON a => a -> ByteString-encode obj = unsafePerformIO $ runConduitRes- $ CL.sourceList (objToEvents $ toJSON obj)- .| Y.encode+encode = encodeWith defaultEncodeOptions +-- | Encode a value into its YAML representation with custom styling.+--+-- @since 0.10.2.0+encodeWith :: ToJSON a => EncodeOptions -> a -> ByteString+encodeWith opts obj = unsafePerformIO $ runConduitRes+ $ CL.sourceList (objToEvents opts $ toJSON obj)+ .| Y.encodeWith (encodeOptionsFormat opts)+ -- | Encode a value into its YAML representation and save to the given file. encodeFile :: ToJSON a => FilePath -> a -> IO ()-encodeFile fp obj = runConduitRes- $ CL.sourceList (objToEvents $ toJSON obj)- .| Y.encodeFile fp+encodeFile = encodeFileWith defaultEncodeOptions -objToEvents :: Value -> [Y.Event]-objToEvents o = (:) EventStreamStart+-- | Encode a value into its YAML representation with custom styling and save to the given file.+--+-- @since 0.10.2.0+encodeFileWith :: ToJSON a => EncodeOptions -> FilePath -> a -> IO ()+encodeFileWith opts fp obj = runConduitRes+ $ CL.sourceList (objToEvents opts $ toJSON obj)+ .| Y.encodeFileWith (encodeOptionsFormat opts) fp++objToEvents :: EncodeOptions -> Value -> [Y.Event]+objToEvents opts o = (:) EventStreamStart . (:) EventDocumentStart $ objToEvents' o [ EventDocumentEnd , EventStreamEnd ]+ where+ objToEvents' :: Value -> [Y.Event] -> [Y.Event]+ --objToEvents' (Scalar s) rest = scalarToEvent s : rest+ objToEvents' (Array list) rest =+ EventSequenceStart NoTag AnySequence Nothing+ : foldr objToEvents' (EventSequenceEnd : rest) (V.toList list)+ objToEvents' (Object pairs) rest =+ EventMappingStart NoTag AnyMapping Nothing+ : foldr pairToEvents (EventMappingEnd : rest) (M.toList pairs) + objToEvents' (String "") rest = EventScalar "" NoTag SingleQuoted Nothing : rest++ objToEvents' (String s) rest = EventScalar (encodeUtf8 s) tag style Nothing : rest+ where+ ( tag, style ) = encodeOptionsStringStyle opts s+ objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest+ objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest+ objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest+ -- Use aeson's implementation which gets rid of annoying decimal points+ objToEvents' n@Number{} rest = EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder n) IntTag PlainNoTag Nothing : rest++ pairToEvents :: Pair -> [Y.Event] -> [Y.Event]+ pairToEvents (k, v) = objToEvents' (String k) . objToEvents' v+ {- FIXME scalarToEvent :: YamlScalar -> Event scalarToEvent (YamlScalar v t s) = EventScalar v t s Nothing -} -objToEvents' :: Value -> [Y.Event] -> [Y.Event]---objToEvents' (Scalar s) rest = scalarToEvent s : rest-objToEvents' (Array list) rest =- EventSequenceStart NoTag AnySequence Nothing- : foldr objToEvents' (EventSequenceEnd : rest) (V.toList list)-objToEvents' (Object pairs) rest =- EventMappingStart NoTag AnyMapping Nothing- : foldr pairToEvents (EventMappingEnd : rest) (M.toList pairs)---- Empty strings need special handling to ensure they get quoted. This avoids:--- https://github.com/snoyberg/yaml/issues/24-objToEvents' (String "") rest = EventScalar "" NoTag SingleQuoted Nothing : rest--objToEvents' (String s) rest =- event : rest- 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-objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest-objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest-objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest--- Use aeson's implementation which gets rid of annoying decimal points-objToEvents' n@Number{} rest = EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder n) IntTag PlainNoTag Nothing : rest--pairToEvents :: Pair -> [Y.Event] -> [Y.Event]-pairToEvents (k, v) = objToEvents' (String k) . objToEvents' v decode :: FromJSON a => ByteString
src/Data/Yaml/Builder.hs view
@@ -14,8 +14,12 @@ , scientific , number , toByteString+ , toByteStringWith , writeYamlFile+ , writeYamlFileWith , (.=)+ , FormatOptions+ , setWidth ) where import Prelude hiding (null)@@ -110,7 +114,17 @@ toSource = mapM_ yield . toEvents . toYaml toByteString :: ToYaml a => a -> ByteString-toByteString yb = unsafePerformIO $ runConduitRes $ toSource yb .| encode+toByteString = toByteStringWith defaultFormatOptions +-- |+-- @since 0.10.2.0+toByteStringWith :: ToYaml a => FormatOptions -> a -> ByteString+toByteStringWith opts yb = unsafePerformIO $ runConduitRes $ toSource yb .| encodeWith opts+ writeYamlFile :: ToYaml a => FilePath -> a -> IO ()-writeYamlFile fp yb = runConduitRes $ toSource yb .| encodeFile fp+writeYamlFile = writeYamlFileWith defaultFormatOptions++-- |+-- @since 0.10.2.0+writeYamlFileWith :: ToYaml a => FormatOptions -> FilePath -> a -> IO ()+writeYamlFileWith opts fp yb = runConduitRes $ toSource yb .| encodeFileWith opts fp
src/Text/Libyaml.hs view
@@ -21,9 +21,14 @@ , Anchor -- * Encoding and decoding , encode+ , encodeWith , decode , encodeFile , decodeFile+ , encodeFileWith+ , FormatOptions+ , defaultFormatOptions+ , setWidth -- * Error handling , YamlException (..) , YamlMark (..)@@ -348,6 +353,9 @@ foreign import ccall unsafe "yaml_emitter_set_output_file" c_yaml_emitter_set_output_file :: Emitter -> File -> IO () +foreign import ccall unsafe "yaml_emitter_set_width"+ c_yaml_emitter_set_width :: Emitter -> CInt -> IO ()+ foreign import ccall unsafe "yaml_emitter_emit" c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt @@ -605,9 +613,34 @@ return $ Left $ YamlParseException problem context problemMark else Right <$> getEvent er +-- | Contains options relating to the formatting (indendation, width) of the YAML output.+--+-- @since 0.10.2.0+data FormatOptions = FormatOptions+ { formatOptionsWidth :: Maybe Int+ }++-- |+-- @since 0.10.2.0+defaultFormatOptions :: FormatOptions+defaultFormatOptions = FormatOptions+ { formatOptionsWidth = Just 80 -- by default the width is set to 0 in the C code, which gets turned into 80 in yaml_emitter_emit_stream_start+ }++-- | Set the maximum number of columns in the YAML output, or 'Nothing' for infinite. By default, the limit is 80 characters.+--+-- @since 0.10.2.0+setWidth :: Maybe Int -> FormatOptions -> FormatOptions+setWidth w opts = opts { formatOptionsWidth = w }+ encode :: MonadResource m => ConduitM Event o m ByteString-encode =- runEmitter alloc close+encode = encodeWith defaultFormatOptions++-- |+-- @since 0.10.2.0+encodeWith :: MonadResource m => FormatOptions -> ConduitM Event o m ByteString+encodeWith opts =+ runEmitter opts alloc close where alloc emitter = do fbuf <- mallocForeignPtrBytes bufferSize@@ -620,11 +653,20 @@ fptr <- newForeignPtr_ $ castPtr ptr' return $ B.fromForeignPtr fptr 0 $ fromIntegral len + encodeFile :: MonadResource m => FilePath -> ConduitM Event o m ()-encodeFile filePath =- bracketP getFile c_fclose $ \file -> runEmitter (alloc file) (\u _ -> return u)+encodeFile = encodeFileWith defaultFormatOptions++-- |+-- @since 0.10.2.0+encodeFileWith :: MonadResource m+ => FormatOptions+ -> FilePath+ -> ConduitM Event o m ()+encodeFileWith opts filePath =+ bracketP getFile c_fclose $ \file -> runEmitter opts (alloc file) (\u _ -> return u) where getFile = do file <- openFile filePath write_flags "w"@@ -635,10 +677,11 @@ alloc file emitter = c_yaml_emitter_set_output_file emitter file runEmitter :: MonadResource m- => (Emitter -> IO a) -- ^ alloc+ => FormatOptions+ -> (Emitter -> IO a) -- ^ alloc -> (() -> a -> IO b) -- ^ close -> ConduitM Event o m b-runEmitter allocI closeI =+runEmitter opts allocI closeI = bracketP alloc cleanup go where alloc = mask_ $ do@@ -648,6 +691,9 @@ #ifndef __NO_UNICODE__ c_yaml_emitter_set_unicode emitter 1 #endif+ c_yaml_emitter_set_width emitter $ case formatOptionsWidth opts of+ Nothing -> -1 --infinite+ Just width -> fromIntegral width a <- allocI emitter return (emitter, a) cleanup (emitter, _) = do
yaml.cabal view
@@ -1,13 +1,13 @@-cabal-version: >= 1.10+cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.29.6.+-- This file has been generated from package.yaml by hpack version 0.30.0. -- -- see: https://github.com/sol/hpack ----- hash: 35f17bf7ece306fc322476ea7dac5e0561ed45dfaf86b2cf65b37c02ed42833f+-- hash: 58011fe7948e28cb6cfcf77813829fd465ad17525a4a24c3babd4155e0df8acd name: yaml-version: 0.10.1.1+version: 0.10.2.0 synopsis: Support for parsing and rendering YAML documents. description: README and API documentation are available at <https://www.stackage.org/package/yaml> category: Data@@ -21,21 +21,21 @@ build-type: Simple extra-source-files: c/helper.h- ChangeLog.md- libyaml/LICENSE- libyaml/yaml.h libyaml/yaml_private.h- README.md- test/json.yaml+ libyaml/yaml.h+ libyaml/LICENSE test/largest-string.yaml- test/resources/accent/foo.yaml+ test/json.yaml+ test/resources/foo.yaml test/resources/bar.yaml test/resources/baz.yaml+ test/resources/accent/foo.yaml+ test/resources/loop/foo.yaml+ test/resources/loop/bar.yaml test/resources/empty.yaml test/resources/empty2.yaml- test/resources/foo.yaml- test/resources/loop/bar.yaml- test/resources/loop/foo.yaml+ README.md+ ChangeLog.md source-repository head type: git