BSD-3-Clause licensed and maintained by Brandon Chinn
This version can be pinned in stack with:kdl-hs-1.0.0@sha256:08d086ffe44d9787aea28dd95d90c11a6ce51ef912abaf0cd8fe7e73bc976a17,2179

kdl-hs

GitHub Actions

kdl-hs can parse and manage KDL configuration files.

Quickstart

Given a file config.kdl:

package {
  name my-pkg
  version "1.2.3"

  dependencies {
    aeson ">= 2.2.3.0" optional=#true
    text ">= 2"
  }
}

Parse it with kdl-hs:

import KDL qualified

main :: IO ()
main = do
  config <- KDL.decodeFileWith decoder "config.kdl"
  print config

decoder :: KDL.DocumentDecoder Config
decoder = KDL.document $ do
  KDL.node "package"

data Config = Config
  { name :: Text
  , version :: Text
  , dependencies :: Map Text Dep
  }
  deriving (Show)

data Dep = Dep
  { version :: Text
  , optional :: Bool
  }
  deriving (Show)

instance KDL.DecodeNode Config where
  nodeDecoder = do
    name <- KDL.argAt "name"
    version <- KDL.argAt "version"
    dependencies <- KDL.nodeWith "dependencies" . KDL.children $ KDL.remainingNodes
    pure Config{..}

instance KDL.DecodeNode Dep where
  nodeDecoder = do
    version <- KDL.arg
    optional <- KDL.option False $ KDL.prop "optional"
    pure Dep{..}

Acknowledgements

  • The KDL spec authors for devising a super cool configuration language
  • kdl-rs for providing a guide for implementation
  • hustle for the initial parser implementation that got me started.

Changes

v1.0.0

  • Implement KDL v2 parser
  • Implement KDL.render, which is format-preserving
  • Improve rendering parse errors
  • Include filepath in error messages when decodeFileWith fails
  • Support adding span information

API changes:

  • Rename Text constructor to String in ValueData
  • Overhauled *Format data types
  • Removed selector functions (e.g. nodeName => (.name) or Node{name})

v0.2.1

  • Add KDL.Applicative
  • Re-export Control.Arrow and Control.Category from KDL.Arrow, for convenience

v0.2.0

  • Remove monad Decoder newtype, just give the Monad instance to the canonical Decoder type and use the same Decoder type everywhere
  • Reorganize module structure
  • Schema improvements
  • Rename Decoder => DecodeArrow, set Decoder o a as alias for DecodeArrow o () a
  • Use v2 syntax for #true/#false/#null

v0.1.0

Initial release, with:

  • Support for decoding v1 KDL syntax (and a subset of v2 KDL syntax)
  • Decoding via Arrows or Monads
  • Statically determine decoder schema