packages feed

salak-toml (empty) → 0.2.7

raw patch · 7 files changed

+474/−0 lines, 7 filesdep +QuickCheckdep +basedep +hspecsetup-changed

Dependencies added: QuickCheck, base, hspec, mtl, salak, text, time, tomland, unordered-containers

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Daniel YU (c) 2019++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Daniel YU nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# salak-yaml
+ Setup.hs view
@@ -0,0 +1,2 @@+import           Distribution.Simple+main = defaultMain
+ salak-toml.cabal view
@@ -0,0 +1,50 @@+cabal-version: 1.12+name: salak-toml+version: 0.2.7+license: BSD3+license-file: LICENSE+copyright: (c) 2018 Daniel YU+maintainer: Daniel YU <leptonyu@gmail.com>+author: Daniel YU+homepage: https://github.com/leptonyu/salak#readme+synopsis: Configuration Loader for toml+category: Library, Configuration+build-type: Simple+extra-source-files:+    README.md+    test/salak.toml++library+    exposed-modules:+        Salak.Load.Toml+    hs-source-dirs: src+    other-modules:+        Paths_salak_toml+    default-language: Haskell2010+    build-depends:+        base >=4.10 && <5,+        mtl >=2.2.2 && <2.3,+        salak ==0.2.7,+        text >=1.2.3.1 && <1.3,+        time >=1.8.0.2 && <1.9,+        tomland ==1.0.*,+        unordered-containers >=0.2.9.0 && <0.3++test-suite spec+    type: exitcode-stdio-1.0+    main-is: Spec.hs+    hs-source-dirs: test src+    other-modules:+        Salak.Load.Toml+        Paths_salak_toml+    default-language: Haskell2010+    build-depends:+        QuickCheck >=2.12.6.1 && <2.14,+        base >=4.10 && <5,+        hspec ==2.*,+        mtl >=2.2.2 && <2.3,+        salak ==0.2.7,+        text >=1.2.3.1 && <1.3,+        time >=1.8.0.2 && <1.9,+        tomland ==1.0.*,+        unordered-containers >=0.2.9.0 && <0.3
+ src/Salak/Load/Toml.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE GADTs           #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections   #-}+module Salak.Load.Toml where++import           Control.Monad          (foldM, (>=>))+import           Control.Monad.IO.Class (MonadIO, liftIO)+import           Control.Monad.State+import qualified Data.HashMap.Strict    as HM+import qualified Data.List.NonEmpty     as N+import qualified Data.Text.IO           as IO+import           Data.Time+import           Salak+import           Salak.Load+import           Toml                   hiding (TOML)+import qualified Toml                   as T++data TOML = TOML++instance HasLoad TOML where+  loaders _ = (, loadToml) <$> ["toml", "tml"]++toSs :: Key -> [Selector]+toSs (Key ps) = toS <$> N.toList ps++toS :: Piece -> Selector+toS = SStr . unPiece++loadTOML :: Reload -> T.TOML -> SourcePack -> SourcePack+loadTOML name v sp = loadFile name sp $ go v+  where+    go T.TOML{..} i s = HM.foldlWithKey' (g1 i) (return s) tomlPairs+                  >>= h2 i tomlTables+    g1 i ms k v' = ms >>= updateSources (toSs k) (f1 i v')+    g2 i ms _ v' = ms >>= f2 i v'+    f1 :: Monad m => Priority -> AnyValue -> Source -> m Source+    f1 i (AnyValue (Array   b)) = \s -> foldM (\s' (ix,x) -> updateSource (SNum ix) (f1 i $ AnyValue x) s') s $ zip [0..] b+    f1 i (AnyValue (Bool    b)) = return . insertSource (VBool  i b)+    f1 i (AnyValue (Integer b)) = return . insertSource (VNum   i $ fromIntegral b)+    f1 i (AnyValue (Double  b)) = return . insertSource (VNum   i $ realToFrac b)+    f1 i (AnyValue (Text    b)) = return . insertSource (VStr   i b)+    f1 i (AnyValue (Local   b)) = return . insertSource (VLTime i b)+    f1 i (AnyValue (Day     b)) = return . insertSource (VDay   i b)+    f1 i (AnyValue (Hours   b)) = return . insertSource (VHour  i b)+    f1 i (AnyValue (Zoned (ZonedTime a b))) = return . insertSource (VZTime i b a)+    -- f1 i _ = return+    f2 :: Monad m => Priority -> PrefixTree T.TOML -> Source -> m Source+    f2 i (Leaf   k     toml) = updateSources (toSs k) (go toml i)+    f2 i (Branch k v' tomap) = updateSources (toSs k) (h1 i v' >=> h2 i tomap)+    h1 :: Monad m => Priority -> Maybe T.TOML -> Source -> m Source+    h1 i (Just t) = go t i+    h1 _ _        = return+    h2 :: Monad m => Priority -> PrefixMap T.TOML -> Source -> m Source+    h2 i m s = HM.foldlWithKey' (g2 i) (return s) m++loadToml :: MonadIO m => FilePath -> SourcePackT m ()+loadToml file = do+    re <- liftIO $ parse <$> IO.readFile file+    modify $ \sp ->case re of+        Left  e -> addErr' (show e) sp+        Right a -> loadTOML (defReload file $ loadToml file) a sp
+ test/Spec.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Main where++import           Control.Monad.Reader+import           Control.Monad.Writer+import           Data.Either+import           Data.List            (intercalate)+import           Data.Text            (Text, pack, unpack)+import           GHC.Generics+import           Salak+import           Salak.Load.Toml+import           Test.Hspec+import           Test.QuickCheck++main = hspec spec++spec :: Spec+spec = do+  describe "Salak.Load.Toml"  tomlProperty++newtype SKey = SKey { unKey :: Text } deriving Show++instance Arbitrary SKey where+  arbitrary = do+    key <- choose (1,20)+    vs  <- vectorOf key $ do+      k <- choose (1,20)+      v <- vectorOf k $ choose ('a','z')+      b <- choose (0,10) :: Gen Int+      if b > 0 then return v else do+        x <- choose (0,10) :: Gen Int+        return (v ++ "[" ++ show x ++ "]")+    return (SKey $ pack $ intercalate "." vs)++data Conf = Conf+  { name :: String+  , age  :: Int+  , male :: Bool+  , det  :: SubConf+  } deriving (Eq, Show, Generic)++data SubConf = SubConf+  { hello :: String } deriving (Eq, Show, Generic)++instance FromProp SubConf where+  fromProp = SubConf <$> "hello" .?= "yyy"++instance FromProp Conf++tomlProperty = do+  context "load toml" $ do+    it "salak.toml" $ do+      loadAndRunSalak (loadToml "test/salak.toml") $ do+        cf <- require "me.icymint.conf"+        lift $ do+          name cf `shouldBe` "shelly"+          age  cf `shouldBe` 16+          male cf `shouldBe` False+          det  cf `shouldBe` SubConf "def"+++++
+ test/salak.toml view
@@ -0,0 +1,261 @@+server.port        = 8080+server.codes       = [ 5, 10, 42 ]+server.description = """+This is production server.+Don't touch it!+"""++[mail]+    host = "smtp.gmail.com"+    send-if-inactive = false++[me.icymint.conf]+name="shelly"+age=16+male="no"+det.hello="def"++################################################################################+## Comment++# Speak your mind with the hash symbol. They go from the symbol to the end of+# the line.+++################################################################################+## Table++# Tables (also known as hash tables or dictionaries) are collections of+# key/value pairs. They appear in square brackets on a line by themselves.++[table]++key = "value" # Yeah, you can do this.++# Nested tables are denoted by table names with dots in them. Name your tables+# whatever crap you please, just don't use #, ., [ or ].++[table.subtable]++key = "another value"++# You don't need to specify all the super-tables if you don't want to. TOML+# knows how to do it for you.++# [x] you+# [x.y] don't+# [x.y.z] need these+[x.y.z.w] # for this to work+++################################################################################+## Inline Table++# Inline tables provide a more compact syntax for expressing tables. They are+# especially useful for grouped data that can otherwise quickly become verbose.+# Inline tables are enclosed in curly braces `{` and `}`. No newlines are+# allowed between the curly braces unless they are valid within a value.++[table.inline]++name = { first = "Tom", last = "Preston-Werner" }+point = { x = 1, y = 2 }+++################################################################################+## String++# There are four ways to express strings: basic, multi-line basic, literal, and+# multi-line literal. All strings must contain only valid UTF-8 characters.++[string.basic]++basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."++[string.multiline]++# The following strings are byte-for-byte equivalent:+key1 = "One\nTwo"+key2 = """One\nTwo"""+key3 = """+One+Two"""++[string.multiline.continued]++# The following strings are byte-for-byte equivalent:+key1 = "The quick brown fox jumps over the lazy dog."++key2 = """+The quick brown \+++  fox jumps over \+    the lazy dog."""++key3 = """\+       The quick brown \+       fox jumps over \+       the lazy dog.\+       """++[string.literal]++# What you see is what you get.+winpath  = 'C:\Users\nodejs\templates'+winpath2 = '\\ServerX\admin$\system32\'+quoted   = 'Tom "Dubs" Preston-Werner'+regex    = '<\i\c*\s*>'+++[string.literal.multiline]++regex2 = '''I [dw]on't need \d{2} apples'''+lines  = '''+The first newline is+trimmed in raw strings.+   All other whitespace+   is preserved.+'''+++################################################################################+## Integer++# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.+# Negative numbers are prefixed with a minus sign.++[integer]++key1 = +99+key2 = 42+key3 = 0+key4 = -17++[integer.underscores]++# For large numbers, you may use underscores to enhance readability. Each+# underscore must be surrounded by at least one digit.+key1 = 1_000+key2 = 5_349_221+key3 = 1_2_3_4_5     # valid but inadvisable+++################################################################################+## Float++# A float consists of an integer part (which may be prefixed with a plus or+# minus sign) followed by a fractional part and/or an exponent part.++[float.fractional]++key1 = +1.0+key2 = 3.1415+key3 = -0.01++[float.exponent]++key1 = 5e+22+key2 = 1e6+key3 = -2E-2++[float.both]++key = 6.626e-34++[float.underscores]++key1 = 9_224_617.445_991_228_313+key2 = 1e1_000+++################################################################################+## Boolean++# Booleans are just the tokens you're used to. Always lowercase.++[boolean]++True = true+False = false+++################################################################################+## Datetime++# Datetimes are RFC 3339 dates.++[datetime]++key1 = 1979-05-27T07:32:00Z+key2 = 1979-05-27T00:32:00-07:00+key3 = 1979-05-27T00:32:00.999999-07:00+++################################################################################+## Array++# Arrays are square brackets with other primitives inside. Whitespace is+# ignored. Elements are separated by commas. Data types may not be mixed.++[array]++key1 = [ 1, 2, 3 ]+key2 = [ "red", "yellow", "green" ]+key3 = [ [ 1, 2 ], [3, 4, 5] ]+key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok++# Arrays can also be multiline. So in addition to ignoring whitespace, arrays+# also ignore newlines between the brackets.  Terminating commas are ok before+# the closing bracket.++key5 = [+  1, 2, 3+]+key6 = [+  1,+  2, # this is ok+]+++################################################################################+## Array of Tables++# These can be expressed by using a table name in double brackets. Each table+# with the same double bracketed name will be an element in the array. The+# tables are inserted in the order encountered.++[[products]]++name = "Hammer"+sku = 738594937++[[products]]++[[products]]++name = "Nail"+sku = 284758393+color = "gray"+++# You can create nested arrays of tables as well.++[[fruit]]+  name = "apple"++  [fruit.physical]+    color = "red"+    shape = "round"++  [[fruit.variety]]+    name = "red delicious"++  [[fruit.variety]]+    name = "granny smith"++[[fruit]]+  name = "banana"++  [[fruit.variety]]+    name = "plantain"