on master help sign in
handle true/y/on/yes/false/n/off/no as booleans, with tests
2df8ad9Patrick Hurst
Data/Yaml.hs+7−2
@@ -54,8 +54,10 @@ import qualified Data.Conduit.List as CL
54import Control.Monad.Trans.Class (MonadTrans, lift)
54import Control.Monad.Trans.Class (MonadTrans, lift)
55import Control.Monad.IO.Class (MonadIO, liftIO)
55import Control.Monad.IO.Class (MonadIO, liftIO)
56import Control.Monad (liftM)
56import Control.Monad (liftM)
57+import Data.Char (toUpper)
57import qualified Data.Vector as V
58import qualified Data.Vector as V
58import Data.Text (Text, pack)
59import Data.Text (Text, pack)
60+import qualified Data.Text as T
59import Data.Text.Read (signed, decimal, double)
61import Data.Text.Read (signed, decimal, double)
60import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
62import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
61import Data.Text.Encoding.Error (lenientDecode)
63import Data.Text.Encoding.Error (lenientDecode)
@@ -161,13 +163,16 @@ textToValue :: Style -> Text -> Value
161textToValue SingleQuoted t = String t
163textToValue SingleQuoted t = String t
162textToValue DoubleQuoted t = String t
164textToValue DoubleQuoted t = String t
163textToValue Folded t = String t
165textToValue Folded t = String t
164−textToValue _ "true" = Bool True
165−textToValue _ "false" = Bool False
166textToValue _ "null" = Null
166textToValue _ "null" = Null
167textToValue _ t
167textToValue _ t
168+ | any (t `isLike`) ["y", "yes", "on", "true"] = Bool True
169+ | any (t `isLike`) ["n", "no", "off", "false"] = Bool False
168 | Right (x, "") <- signed decimal t = Number $ I x
170 | Right (x, "") <- signed decimal t = Number $ I x
169 | Right (x, "") <- double t = Number $ D x
171 | Right (x, "") <- double t = Number $ D x
170 | otherwise = String t
172 | otherwise = String t
173+ where x `isLike` ref = x `elem` [ref, T.toUpper ref, titleCased]
174+ where titleCased = toUpper (T.head ref) `T.cons` T.tail ref
175+
171
176
172parseO :: C.Sink Event Parse Value
177parseO :: C.Sink Event Parse Value
173parseO = do
178parseO = do
test/main.hs+12
@@ -56,6 +56,10 @@ main = hspecX $ do
56 describe "numbers" $ do
56 describe "numbers" $ do
57 it "parses as string when quoted" caseQuotedNumber
57 it "parses as string when quoted" caseQuotedNumber
58 it "parses as number when unquoted" caseUnquotedNumber
58 it "parses as number when unquoted" caseUnquotedNumber
59+ describe "booleans" $ do
60+ it "parses when all lowercase" caseLowercaseBool
61+ it "parses when all uppercase" caseUppercaseBool
62+ it "parses when titlecase" caseTitlecaseBool
59
63
60counter :: Monad m => (Y.Event -> Bool) -> C.Sink Y.Event m Int
64counter :: Monad m => (Y.Event -> Bool) -> C.Sink Y.Event m Int
61counter pred' =
65counter pred' =
@@ -308,3 +312,11 @@ caseDataTypes =
308caseQuotedNumber, caseUnquotedNumber :: Assertion
312caseQuotedNumber, caseUnquotedNumber :: Assertion
309caseQuotedNumber = D.decode "foo: \"1234\"" @?= Just (object [("foo", D.String "1234")])
313caseQuotedNumber = D.decode "foo: \"1234\"" @?= Just (object [("foo", D.String "1234")])
310caseUnquotedNumber = D.decode "foo: 1234" @?= Just (object [("foo", D.Number 1234)])
314caseUnquotedNumber = D.decode "foo: 1234" @?= Just (object [("foo", D.Number 1234)])
315+
316+obj :: Maybe D.Value
317+obj = Just (object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)])
318+
319+caseLowercaseBool, caseUppercaseBool, caseTitlecaseBool :: Assertion
320+caseLowercaseBool = D.decode "foo: off\nbar: y\nbaz: true" @?= obj
321+caseUppercaseBool = D.decode "foo: FALSE\nbar: Y\nbaz: ON" @?= obj
322+caseTitlecaseBool = D.decode "foo: No\nbar: Yes\nbaz: True" @?= obj