packages feed

config-ini 0.2.1.1 → 0.2.2.0

raw patch · 3 files changed

+82/−8 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Data.Ini.Config: sectionOf :: (Text -> Maybe b) -> (b -> SectionParser a) -> IniParser a
+ Data.Ini.Config: sections :: Text -> SectionParser a -> IniParser (Seq a)
+ Data.Ini.Config: sectionsOf :: (Text -> Maybe b) -> (b -> SectionParser a) -> IniParser (Seq a)
- Data.Ini.Config.Bidir: (&) :: a -> (a -> b) -> b
+ Data.Ini.Config.Bidir: (&) :: () => a -> (a -> b) -> b

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+0.2.2.0+=======++- Added `sections`, `sectionOf`, and `sectionsOf` helpers to the+  vanilla API for more flexibility in working with section names+- Put `test-doctest` behind a flag, which is disabled by default+ 0.2.1.1 ======= 
config-ini.cabal view
@@ -1,5 +1,5 @@ name:             config-ini-version:          0.2.1.1+version:          0.2.2.0 synopsis:         A library for simple INI-based configuration files. homepage:         https://github.com/aisamanra/config-ini bug-reports:      https://github.com/aisamanra/config-ini/issues@@ -18,7 +18,7 @@ license-file:     LICENSE author:           Getty Ritter <config-ini@infinitenegativeutility.com> maintainer:       Getty Ritter <config-ini@infinitenegativeutility.com>-copyright:        ©2017 Getty Ritter+copyright:        ©2018 Getty Ritter category:         Configuration build-type:       Simple cabal-version:    >= 1.18@@ -33,6 +33,10 @@   type: git   location: git://github.com/aisamanra/config-ini.git +flag enable-doctests+  description: Build doctest modules as well (can be finicky)+  default:     False+ library   hs-source-dirs:      src   exposed-modules:     Data.Ini.Config@@ -75,7 +79,7 @@                   , directory  test-suite test-doctest-  if impl(ghc < 7.10)+  if impl(ghc < 7.10) || !flag(enable-doctests)     buildable:      False   type:             exitcode-stdio-1.0   ghc-options:      -Wall
src/Data/Ini/Config.hs view
@@ -12,7 +12,7 @@ For example, the following INI file has two sections, @NETWORK@ and @LOCAL@, and each contains its own key-value pairs. Comments, which begin with @#@ or @;@, are ignored:---+ > [NETWORK] > host = example.com > port = 7878@@ -20,7 +20,7 @@ > # here is a comment > [LOCAL] > user = terry---+ The combinators provided here are designed to write quick and idiomatic parsers for files of this form. Sections are parsed by 'IniParser' computations, like 'section' and its variations,@@ -28,7 +28,7 @@ computations, like 'field' and its variations. If we want to parse an INI file like the one above, treating the entire @LOCAL@ section as optional, we can write it like this:---+ > data Config = Config >   { cfNetwork :: NetworkConfig, cfLocal :: Maybe LocalConfig } >     deriving (Eq, Show)@@ -50,11 +50,12 @@ >   locCf <- sectionMb "LOCAL" $ >     LocalConfig <$> field "user" >   return Config { cfNetwork = netCf, cfLocal = locCf }---++ We can run our computation with 'parseIniFile', which, when run on our example file above, would produce the following:---+ >>> parseIniFile example configParser Right (Config {cfNetwork = NetworkConfig {netHost = "example.com", netPort = 7878}, cfLocal = Just (LocalConfig {localUser = "terry"})}) @@ -73,6 +74,9 @@ , SectionParser -- * Section-Level Parsing , section+, sections+, sectionOf+, sectionsOf , sectionMb , sectionDef -- * Field-Level Parsing@@ -149,6 +153,65 @@   case lkp (normalize name) ini of     Nothing  -> Left ("No top-level section named " ++ show name)     Just sec -> runExceptT thunk sec++-- | Find multiple named sections in the INI file and parse them all+--   with the provided section parser. In order to support classic INI+--   files with capitalized section names, section lookup is+--   __case-insensitive__.+--+--   >>> parseIniFile "[ONE]\nx = hello\n[ONE]\nx = goodbye\n" $ sections "ONE" (field "x")+--   Right (fromList ["hello","goodbye"])+--   >>> parseIniFile "[ONE]\nx = hello\n" $ sections "TWO" (field "x")+--   Right (fromList [])+sections :: Text -> SectionParser a -> IniParser (Seq a)+sections name (SectionParser thunk) = IniParser $ ExceptT $ \(RawIni ini) ->+  let name' = normalize name+  in mapM (runExceptT thunk . snd)+          (Seq.filter (\ (t, _) -> t == name') ini)++-- | A call to @sectionOf f@ will apply @f@ to each section name and,+--   if @f@ produces a "Just" value, pass the extracted value in order+--   to get the "SectionParser" to use for that section. This will+--   find at most one section, and will produce an error if no section+--   exists.+--+--   >>> parseIniFile "[FOO]\nx = hello\n" $ sectionOf (T.stripSuffix "OO") (\ l -> fmap ((,) l) (field "x"))+--   Right ("F","hello")+--   >>> parseIniFile "[BAR]\nx = hello\n" $ sectionOf (T.stripSuffix "OO") (\ l -> fmap ((,) l) (field "x"))+--   Left "No matching top-level section"+sectionOf :: (Text -> Maybe b) -> (b -> SectionParser a) -> IniParser a+sectionOf fn sectionParser = IniParser $ ExceptT $ \(RawIni ini) ->+  let go Seq.EmptyL = Left "No matching top-level section"+      go ((t, sec) Seq.:< rs)+        | Just v <- fn (actualText t) =+            let SectionParser thunk = sectionParser v+            in runExceptT thunk sec+        | otherwise = go (Seq.viewl rs)+  in go (Seq.viewl ini)+++-- | A call to @sectionsOf f@ will apply @f@ to each section name and,+--   if @f@ produces a @Just@ value, pass the extracted value in order+--   to get the "SectionParser" to use for that section. This will+--   return every section for which the call to @f@ produces a "Just"+--   value.+--+--   >>> parseIniFile "[FOO]\nx = hello\n[BOO]\nx = goodbye\n" $ sectionsOf (T.stripSuffix "OO") (\ l -> fmap ((,) l) (field "x"))+--   Right (fromList [("F","hello"),("B","goodbye")])+--   >>> parseIniFile "[BAR]\nx = hello\n" $ sectionsOf (T.stripSuffix "OO") (\ l -> fmap ((,) l) (field "x"))+--   Right (fromList [])+sectionsOf :: (Text -> Maybe b) -> (b -> SectionParser a) -> IniParser (Seq a)+sectionsOf fn sectionParser = IniParser $ ExceptT $ \(RawIni ini) ->+  let go Seq.EmptyL = return Seq.empty+      go ((t, sec) Seq.:< rs)+        | Just v <- fn (actualText t) =+            let SectionParser thunk = sectionParser v+            in do+              x <- runExceptT thunk sec+              xs <- go (Seq.viewl rs)+              return (x Seq.<| xs)+        | otherwise = go (Seq.viewl rs)+  in go (Seq.viewl ini)  -- | Find a named section in the INI file and parse it with the provided --   section parser, returning 'Nothing' if the section does not exist.