packages feed

lens-toml-parser (empty) → 0.1.0.0

raw patch · 10 files changed

+728/−0 lines, 10 filesdep +basedep +containersdep +dwergazsetup-changed

Dependencies added: base, containers, dwergaz, hlint, lens-simple, lens-toml-parser, profunctors, text, time, toml-parser

Files

+ .gitignore view
@@ -0,0 +1,4 @@+dist/+dist-newstyle/+shell.nix+cabal.project.local
+ .travis.yml view
@@ -0,0 +1,92 @@+# This Travis job script has been generated by a script via+#+#   make_travis_yml_2.hs 'lens-toml-parser.cabal'+#+# For more information, see https://github.com/hvr/multi-ghc-travis+#+language: c+sudo: false++git:+  submodules: false  # whether to recursively clone submodules++cache:+  directories:+    - $HOME/.cabal/packages+    - $HOME/.cabal/store++before_cache:+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log+  # remove files that are regenerated by 'cabal update'+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx++matrix:+  include:+    - compiler: "ghc-8.0.2"+    # env: TEST=--disable-tests BENCH=--disable-benchmarks+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.0.2], sources: [hvr-ghc]}}+    - compiler: "ghc-8.2.1"+    # env: TEST=--disable-tests BENCH=--disable-benchmarks+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.2.1], sources: [hvr-ghc]}}++before_install:+ - HC=${CC}+ - HCPKG=${HC/ghc/ghc-pkg}+ - unset CC+ - PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$PATH+ - PKGNAME='lens-toml-parser'++install:+ - cabal --version+ - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"+ - BENCH=${BENCH---enable-benchmarks}+ - TEST=${TEST---enable-tests}+ - HADDOCK=${HADDOCK-true}+ - INSTALLED=${INSTALLED-true}+ - travis_retry cabal update -v+ - sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config+ - rm -fv cabal.project.local+ - "echo 'packages: .' > cabal.project"+ - rm -f cabal.project.freeze+ - cabal new-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all++# Here starts the actual work to be performed for the package under test;+# any command which exits with a non-zero exit code causes the build to fail.+script:+ - if [ -f configure.ac ]; then autoreconf -i; fi+ - rm -rf .ghc.environment.* dist/+ - cabal sdist # test that a source-distribution can be generated+ - cd dist/+ - SRCTAR=(${PKGNAME}-*.tar.gz)+ - SRC_BASENAME="${SRCTAR/%.tar.gz}"+ - tar -xvf "./$SRC_BASENAME.tar.gz"+ - cd "$SRC_BASENAME/"+## from here on, CWD is inside the extracted source-tarball+ - rm -fv cabal.project.local+ - "echo 'packages: .' > cabal.project"+ # this builds all libraries and executables (without tests/benchmarks)+ - rm -f cabal.project.freeze+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all+ # this builds all libraries and executables (including tests/benchmarks)+ # - rm -rf ./dist-newstyle++ # Build with installed constraints for packages in global-db+ - if $INSTALLED; then+     echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks $(${HCPKG} list --global --simple-output --names-only | sed 's/\([a-zA-Z0-9-]\{1,\}\) */--constraint="\1 installed" /g') all | sh;+   else echo "Not building with installed constraints"; fi++ # build & run tests, build benchmarks+ - cabal new-build -w ${HC} ${TEST} ${BENCH} all+ - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} all; fi++ # haddock+ - rm -rf ./dist-newstyle+ - if $HADDOCK; then cabal new-haddock -w ${HC} --disable-tests --disable-benchmarks all; else echo "Skipping haddock generation";fi++# REGENDATA ["lens-toml-parser.cabal"]+# EOF
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for lens-toml-parser++## 0.1.0.0  -- 2017-08-14++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,13 @@+Copyright (c) 2017 Henry Till++Permission to use, copy, modify, and/or distribute this software for any purpose+with or without fee is hereby granted, provided that the above copyright notice+and this permission notice appear in all copies.++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF+THIS SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ example/example-v0.4.0.toml view
@@ -0,0 +1,246 @@+################################################################################+## 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"++## toml-parser does handle the following:+#+#   [fruit.physical]+#     color = "red"+#     shape = "round"+#+#   [[fruit.variety]]+#     name = "red delicious"+#+#   [[fruit.variety]]+#     name = "granny smith"+#+# [[fruit]]+#   name = "banana"+#+#   [[fruit.variety]]+#     name = "plantain"
+ lens-toml-parser.cabal view
@@ -0,0 +1,62 @@+-- Initial lens-toml-parser.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                lens-toml-parser+version:             0.1.0.0+synopsis:            Lenses for toml-parser+description:         Lenses for toml-parser+license:             ISC+license-file:        LICENSE+author:              Henry Till+maintainer:          henrytill@gmail.com+homepage:            https://github.com/xngns/lens-toml-parser+copyright:           Copyright (c) 2017, Henry Till+category:            Language, Lenses+build-type:          Simple+cabal-version:       >=1.10+tested-with:         GHC == 8.0.2, GHC == 8.2.1++extra-source-files:+  .gitignore+  .travis.yml+  ChangeLog.md+  example/example-v0.4.0.toml++source-repository head+  type:     git+  location: https://github.com/xngns/lens-toml-parser.git++library+  exposed-modules:     TOML.Lens+  -- other-modules:       +  -- other-extensions:    +  build-depends:       base        >=4.8 && <4.11+                     , text        >=1.2 && <1.3+                     , time        >=1.5 && <1.9+                     , profunctors >=5.2 && <5.3+                     , toml-parser >=0.1 && <0.2+  hs-source-dirs:      src+  default-language:    Haskell2010+  ghc-options:         -Wall++test-suite tests+  type:                exitcode-stdio-1.0+  main-is:             Main.hs+  build-depends:       base        >=4.8 && <4.11+                     , containers  >=0.5 && <0.6+                     , text        >=1.2 && <1.3+                     , dwergaz     >=0.2 && <0.3+                     , toml-parser >=0.1 && <0.2+                     , lens-simple >=0.1 && <0.2+                     , lens-toml-parser+  hs-source-dirs:      tests+  default-language:    Haskell2010+  ghc-options:         -Wall++test-suite hlint+  type:                exitcode-stdio-1.0+  main-is:             HLint.hs+  build-depends:       base+                     , hlint >= 1.9+  hs-source-dirs:      tests+  default-language:    Haskell2010
+ src/TOML/Lens.hs view
@@ -0,0 +1,150 @@+-- |+-- Module      : TOML.Lens+-- Description : Lenses for toml-parser+-- Copyright   : (c) 2017, Henry Till+-- License     : ISC+-- Maintainer  : henrytill@gmail.com+-- Stability   : experimental+--+-- Lenses for <https://hackage.haskell.org/package/toml-parser toml-parser>.+--+module TOML.Lens+  ( _Table+  , _List+  , _Double+  , _Integer+  , _String+  , _Bool+  , _ZonedTimeV+  , _LocalTimeV+  , _DayV+  , _TimeOfDayV+  ) where++import           Data.Profunctor+import qualified Data.Text       as T+import           Data.Time++import           TOML++--+-- With help from:+-- <https://github.com/ekmett/lens/wiki/How-can-I-write-lenses-without-depending-on-lens%3F>+--+-- @+-- type Prism s t a b = (Choice p, Applicative f) => p a (f b) -> p s (f t)+-- @+--+-- @+-- type Prism' s a = Prism s s a a+-- @+--++prism+  :: (Choice p, Applicative f)+  => (b -> t)+  -> (s -> Either t a)+  -> p a (f b)+  -> p s (f t)+prism bt seta = dimap seta (either pure (fmap bt)) . right'+{-# INLINE prism #-}++-- | @_Table :: Prism' Value [(Text, Value)]@+_Table+  :: (Choice p, Applicative f)+  => p [(T.Text, Value)] (f [(T.Text, Value)])+  -> p Value (f Value)+_Table =+  prism Table $ \ n -> case n of+    Table v -> pure v+    _       -> Left n++-- | @_List :: Prism' Value [Value]@+_List+  :: (Choice p, Applicative f)+  => p [Value] (f [Value])+  -> p Value (f Value)+_List =+  prism List $ \ n -> case n of+    List v -> pure v+    _      -> Left n++-- | @_Double :: Prism' Value Double@+_Double+  :: (Choice p, Applicative f)+  => p Double (f Double)+  -> p Value (f Value)+_Double =+  prism Double $ \ n -> case n of+    Double v -> pure v+    _        -> Left n++-- | @_Integer :: Prism' Value Integer@+_Integer+  :: (Choice p, Applicative f)+  => p Integer (f Integer)+  -> p Value (f Value)+_Integer =+  prism Integer $ \ n -> case n of+    Integer v -> pure v+    _         -> Left n++-- | @_String :: Prism' Value T.Text@+_String+  :: (Choice p, Applicative f)+  => p T.Text (f T.Text)+  -> p Value (f Value)+_String =+  prism String $ \ n -> case n of+    String v -> pure v+    _        -> Left n++-- | @_Bool :: Prism' Value Bool@+_Bool+  :: (Choice p, Applicative f)+  => p Bool (f Bool)+  -> p Value (f Value)+_Bool =+  prism Bool $ \ n -> case n of+    Bool v -> pure v+    _      -> Left n++-- | @_ZonedTimeV :: Prism' Value ZonedTime@+_ZonedTimeV+  :: (Choice p, Applicative f)+  => p ZonedTime (f ZonedTime)+  -> p Value (f Value)+_ZonedTimeV =+  prism ZonedTimeV $ \ n -> case n of+    ZonedTimeV v -> pure v+    _            -> Left n++-- | @_LocalTimeV :: Prism' Value LocalTime@+_LocalTimeV+  :: (Choice p, Applicative f)+  => p LocalTime (f LocalTime)+  -> p Value (f Value)+_LocalTimeV =+  prism LocalTimeV $ \ n -> case n of+    LocalTimeV v -> pure v+    _            -> Left n++-- | @_DayV :: Prism' Value Day@+_DayV+  :: (Choice p, Applicative f)+  => p Day (f Day)+  -> p Value (f Value)+_DayV =+  prism DayV $ \ n -> case n of+    DayV v -> pure v+    _      -> Left n++-- | @_TimeOfDayV :: Prism' Value TimeOfDay@+_TimeOfDayV+  :: (Choice p, Applicative f)+  => p TimeOfDay (f TimeOfDay)+  -> p Value (f Value)+_TimeOfDayV =+  prism TimeOfDayV $ \ n -> case n of+    TimeOfDayV v -> pure v+    _            -> Left n
+ tests/HLint.hs view
@@ -0,0 +1,12 @@+module Main (main) where++import Control.Monad+import Language.Haskell.HLint3+import System.Environment+import System.Exit++main :: IO ()+main = do+  args  <- getArgs+  hints <- hlint $ ["src", "tests"] ++ args+  unless (null hints) exitFailure
+ tests/Main.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings #-}++module Main (main) where++import           Control.Monad (unless)+import qualified Data.Map.Lazy as Map+import qualified Data.Text     as T+import           Data.Text.IO  (readFile)+import           Lens.Simple+import           Prelude       hiding (readFile)+import           System.Exit   (exitFailure)+import           Test.Dwergaz+import qualified TOML+import           TOML.Lens+++alist :: Ord k => [(k, v)] -> Map.Map k v+alist = Map.fromList++alistLens+  :: (Ord k1, Ord k2, Functor f)+  => LensLike f [(k1, v1)] [(k2, v2)] (Map.Map k1 v1) (Map.Map k2 v2)+alistLens = iso Map.fromList Map.toList++mapAt+  :: Applicative f+  => T.Text+  -> (Map.Map T.Text TOML.Value -> f (Map.Map T.Text TOML.Value))+  -> Map.Map T.Text TOML.Value+  -> f (Map.Map T.Text TOML.Value)+mapAt k = at k . _Just . _Table . alistLens++listAt+  :: Applicative f+  => T.Text+  -> ([TOML.Value] -> f [TOML.Value])+  -> Map.Map T.Text TOML.Value+  -> f (Map.Map T.Text TOML.Value)+listAt k = at k . _Just . _List++testTableKey :: [(T.Text, TOML.Value)] -> Test+testTableKey kv+  = Expect "'key' from 'table' == Just \"value\""+           (==) expected actual+  where+    expected = Just "value"+    actual   = alist kv ^? mapAt "table" . at "key" . _Just . _String++testTableZoo :: [(T.Text, TOML.Value)] -> Test+testTableZoo kv+  = Expect "'zoo' from 'table' == Nothing"+           (==) expected actual+  where+    expected = Nothing+    actual   = alist kv ^? mapAt "table" . at "zoo" . _Just . _String++testTableSubtableKey :: [(T.Text, TOML.Value)] -> Test+testTableSubtableKey kv+  = Expect "'key' from 'subtable' from 'table' == Just \"another value\""+           (==) expected actual+  where+    expected = Just "another value"+    actual   = alist kv ^? mapAt "table" . mapAt "subtable" . at "key" . _Just . _String++testTableInlineNameFirst :: [(T.Text, TOML.Value)] -> Test+testTableInlineNameFirst kv+  = Expect "'first' from 'name' from 'inline' from 'table' == \"Tom\""+           (==) expected actual+  where+    expected = Just "Tom"+    actual   = alist kv ^? mapAt "table" . mapAt "inline" . mapAt "name" . at "first" . _Just . _String++testTableInlinePointY :: [(T.Text, TOML.Value)] -> Test+testTableInlinePointY kv+  = Expect "'y' from 'point' from 'inline' from 'table' == Just 2"+           (==) expected actual+  where+    expected = Just 2+    actual   = alist kv ^? mapAt "table" . mapAt "inline" . mapAt "point" . at "y" . _Just . _Integer++testStringBasicBasic :: [(T.Text, TOML.Value)] -> Test+testStringBasicBasic kv+  = Expect "'basic' from 'basic' from 'string' == <some escaped nonsense>"+           (==) expected actual+  where+    expected = Just "I'm a string. \"You can quote me\". Name\tJos\233\nLocation\tSF."+    actual   = alist kv ^? mapAt "string" . mapAt "basic" . at "basic" . _Just . _String++testStringMultiline :: [(T.Text, TOML.Value)] -> Test+testStringMultiline kv+  = Predicate "'key1', 'key2', and 'key3' from 'multiline' from 'string' are all the same"+              (\ xs -> all (== head xs) (tail xs))+              [actual1, actual2, actual3]+  where+    actual1 = alist kv ^? mapAt "string" . mapAt "multiline" . at "key1" . _Just . _String+    actual2 = alist kv ^? mapAt "string" . mapAt "multiline" . at "key2" . _Just . _String+    actual3 = alist kv ^? mapAt "string" . mapAt "multiline" . at "key3" . _Just . _String++testStringMultilineContinued :: [(T.Text, TOML.Value)] -> Test+testStringMultilineContinued kv+  = Predicate "'key1', 'key2', and 'key3' from 'continued' from 'multiline' from 'string' are all the same"+              (\ xs -> all (== head xs) (tail xs))+              [actual1, actual2, actual3]+  where+    actual1 = alist kv ^? mapAt "string" . mapAt "multiline" . mapAt "continued" . at "key1" . _Just . _String+    actual2 = alist kv ^? mapAt "string" . mapAt "multiline" . mapAt "continued" . at "key2" . _Just . _String+    actual3 = alist kv ^? mapAt "string" . mapAt "multiline" . mapAt "continued" . at "key3" . _Just . _String++testArrayKey1 :: [(T.Text, TOML.Value)] -> Test+testArrayKey1 kv+  = Expect "'key1' from 'array' == [1, 2, 3]"+           (==) expected actual+  where+    expected = [1, 2, 3]+    actual   = alist kv ^.. mapAt "array" . listAt "key1" . traverse . _Integer++runTests :: [(T.Text, TOML.Value)] -> [Result]+runTests kv = runTest . ($ kv) <$> tests+  where+    tests = [ testTableKey+            , testTableZoo+            , testTableSubtableKey+            , testTableInlineNameFirst+            , testTableInlinePointY+            , testStringBasicBasic+            , testStringMultiline+            , testStringMultilineContinued+            , testArrayKey1+            ]++readTOMLFile :: String -> IO [(T.Text, TOML.Value)]+readTOMLFile file = readFile file >>= parse >>= handleError+  where+    parse       = pure . TOML.parseTOML+    handleError = either (error . show) pure++main :: IO ()+main =  do+  ex <- readTOMLFile "./example/example-v0.4.0.toml"+  rs <- pure (runTests ex)+  _  <- mapM_ print rs+  unless (all isPassed rs) exitFailure