packages feed

ede 0.3.2.0 → 0.3.3.0

raw patch · 9 files changed

+155/−99 lines, 9 filesdep ~aesondep ~attoparsecdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: aeson, attoparsec, base, bytestring

API changes (from Hackage documentation)

- Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote Data.Aeson.Types.Internal.Array
- Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote Data.Aeson.Types.Internal.Object
- Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote Data.Aeson.Types.Internal.Array
- Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote Data.Aeson.Types.Internal.Object
+ Text.EDE.Internal.Compat: fromHashMapText :: HashMap Text v -> KeyMap v
+ Text.EDE.Internal.Compat: toHashMapText :: KeyMap v -> HashMap Text v
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote (Data.Aeson.KeyMap.KeyMap Data.Aeson.Types.Internal.Value)
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote (Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Aeson.Types.Internal.Value)
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Quote (Data.Vector.Vector Data.Aeson.Types.Internal.Value)
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote (Data.Aeson.KeyMap.KeyMap Data.Aeson.Types.Internal.Value)
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote (Data.HashMap.Internal.HashMap Data.Text.Internal.Text Data.Aeson.Types.Internal.Value)
+ Text.EDE.Internal.Quoting: instance Text.EDE.Internal.Quoting.Unquote (Data.Vector.Vector Data.Aeson.Types.Internal.Value)
- Text.EDE: (.=) :: (KeyValue kv, ToJSON v) => Text -> v -> kv
+ Text.EDE: (.=) :: (KeyValue kv, ToJSON v) => Key -> v -> kv
- Text.EDE: delimBlock :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE: delimBlock :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE: delimComment :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE: delimComment :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE: delimInline :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE: delimInline :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE: delimPragma :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE: delimPragma :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE: eitherRender :: Template -> Object -> Either String Text
+ Text.EDE: eitherRender :: Template -> HashMap Text Value -> Either String Text
- Text.EDE: eitherRenderWith :: HashMap Id Term -> Template -> Object -> Either String Text
+ Text.EDE: eitherRenderWith :: HashMap Id Term -> Template -> HashMap Text Value -> Either String Text
- Text.EDE: fromPairs :: [Pair] -> Object
+ Text.EDE: fromPairs :: [Pair] -> HashMap Text Value
- Text.EDE: fromValue :: Value -> Maybe Object
+ Text.EDE: fromValue :: Value -> Maybe (HashMap Text Value)
- Text.EDE: render :: Template -> Object -> Result Text
+ Text.EDE: render :: Template -> HashMap Text Value -> Result Text
- Text.EDE: renderWith :: HashMap Id Term -> Template -> Object -> Result Text
+ Text.EDE: renderWith :: HashMap Id Term -> Template -> HashMap Text Value -> Result Text
- Text.EDE.Filters: qcol1 :: (Quote a, Quote b, Quote c) => Id -> (Text -> a) -> (Object -> b) -> (Array -> c) -> (Id, Term)
+ Text.EDE.Filters: qcol1 :: (Quote a, Quote b, Quote c) => Id -> (Text -> a) -> (HashMap Text Value -> b) -> (Vector Value -> c) -> (Id, Term)
- Text.EDE.Internal.Eval: bind :: (Object -> Object) -> Context a -> Context a
+ Text.EDE.Internal.Eval: bind :: (HashMap Text Value -> HashMap Text Value) -> Context a -> Context a
- Text.EDE.Internal.Filters: headV :: Array -> Value
+ Text.EDE.Internal.Filters: headV :: Vector Value -> Value
- Text.EDE.Internal.Filters: initV :: Array -> Value
+ Text.EDE.Internal.Filters: initV :: Vector Value -> Value
- Text.EDE.Internal.Filters: lastV :: Array -> Value
+ Text.EDE.Internal.Filters: lastV :: Vector Value -> Value
- Text.EDE.Internal.Filters: qcol1 :: (Quote a, Quote b, Quote c) => Id -> (Text -> a) -> (Object -> b) -> (Array -> c) -> (Id, Term)
+ Text.EDE.Internal.Filters: qcol1 :: (Quote a, Quote b, Quote c) => Id -> (Text -> a) -> (HashMap Text Value -> b) -> (Vector Value -> c) -> (Id, Term)
- Text.EDE.Internal.Filters: qlist1 :: (Quote a, Quote b) => Id -> (Text -> a) -> (Array -> b) -> (Id, Term)
+ Text.EDE.Internal.Filters: qlist1 :: (Quote a, Quote b) => Id -> (Text -> a) -> (Vector Value -> b) -> (Id, Term)
- Text.EDE.Internal.Filters: tailV :: Array -> Value
+ Text.EDE.Internal.Filters: tailV :: Vector Value -> Value
- Text.EDE.Internal.Filters: vec :: (Array -> Value) -> Array -> Value
+ Text.EDE.Internal.Filters: vec :: (Vector Value -> Value) -> Vector Value -> Value
- Text.EDE.Internal.Parser: array :: Parser m => m Array
+ Text.EDE.Internal.Parser: array :: Parser m => m (Vector Value)
- Text.EDE.Internal.Parser: object :: Parser m => m Object
+ Text.EDE.Internal.Parser: object :: Parser m => m (HashMap Text Value)
- Text.EDE.Internal.Types: _Failure :: forall a_abo1. Prism' (Result a_abo1) AnsiDoc
+ Text.EDE.Internal.Types: _Failure :: forall a_abTC. Prism' (Result a_abTC) AnsiDoc
- Text.EDE.Internal.Types: _Success :: forall a_abo1 a_ad3E. Prism (Result a_ad3E) (Result a_abo1) a_ad3E a_abo1
+ Text.EDE.Internal.Types: _Success :: forall a_adyU a_abTC. Prism (Result a_adyU) (Result a_abTC) a_adyU a_abTC
- Text.EDE.Internal.Types: class HasSyntax c_adjL
+ Text.EDE.Internal.Types: class HasSyntax c_adP9
- Text.EDE.Internal.Types: delimBlock :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE.Internal.Types: delimBlock :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE.Internal.Types: delimComment :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE.Internal.Types: delimComment :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE.Internal.Types: delimInline :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE.Internal.Types: delimInline :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE.Internal.Types: delimPragma :: HasSyntax c_adjL => Lens' c_adjL Delim
+ Text.EDE.Internal.Types: delimPragma :: HasSyntax c_adP9 => Lens' c_adP9 Delim
- Text.EDE.Internal.Types: fromPairs :: [Pair] -> Object
+ Text.EDE.Internal.Types: fromPairs :: [Pair] -> HashMap Text Value
- Text.EDE.Internal.Types: fromValue :: Value -> Maybe Object
+ Text.EDE.Internal.Types: fromValue :: Value -> Maybe (HashMap Text Value)
- Text.EDE.Internal.Types: syntax :: HasSyntax c_adjL => Lens' c_adjL Syntax
+ Text.EDE.Internal.Types: syntax :: HasSyntax c_adP9 => Lens' c_adP9 Syntax

Files

app/Main.hs view
@@ -8,20 +8,23 @@ import qualified Data.Attoparsec.ByteString as Parsec import qualified Data.ByteString as ByteString import qualified Data.ByteString.Lazy as ByteString.Lazy+import Data.HashMap.Strict (HashMap)+import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text.Encoding import qualified Data.Text.Lazy.IO as Text.Lazy.IO import qualified Options.Applicative as Options import qualified Options.Applicative.Help.Pretty as Pretty-import qualified System.Exit as Exit-import qualified Text.EDE as EDE import qualified Prettyprinter as PP import qualified Prettyprinter.Render.Terminal as PP+import qualified System.Exit as Exit+import qualified Text.EDE as EDE+import qualified Text.EDE.Internal.Compat as Compat  data Options = Options   { templateFile :: FilePath,     jsonFile :: Maybe FilePath,-    jsonObject :: Maybe Aeson.Object+    jsonObject :: Maybe (HashMap Text Aeson.Value)   }  optionsParser :: Options.Parser Options@@ -117,7 +120,7 @@         EDE.Failure err -> PP.putDoc (err <> PP.hardline) >> Exit.exitFailure         EDE.Success output -> Text.Lazy.IO.putStr output -stdinParser :: Parsec.Parser Aeson.Object+stdinParser :: Parsec.Parser (HashMap Text Aeson.Value) stdinParser = Aeson.json >>= requireObject  readValue :: Options.ReadM Aeson.Value@@ -129,10 +132,10 @@     . Text.Encoding.encodeUtf8     . Text.pack -readObject :: Options.ReadM Aeson.Object+readObject :: Options.ReadM (HashMap Text Aeson.Value) readObject = readValue >>= requireObject -requireObject :: Fail.MonadFail m => Aeson.Value -> m Aeson.Object+requireObject :: Fail.MonadFail m => Aeson.Value -> m (HashMap Text Aeson.Value) requireObject = \case-  Aeson.Object obj -> pure obj+  Aeson.Object obj -> pure (Compat.toHashMapText obj)   _ -> fail "JSON value must be an object"
ede.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               ede-version:            0.3.2.0+version:            0.3.3.0 synopsis:   Templating language with similar syntax and features to Liquid or Jinja2. @@ -49,9 +49,9 @@   default-language: Haskell2010   ghc-options:     -Wall -funbox-strict-fields -fwarn-incomplete-uni-patterns-    -fwarn-incomplete-record-updates+    -fwarn-incomplete-record-updates -fwarn-unused-packages -  build-depends:    base >=4.12 && <5+  build-depends:    base >=4.13 && <5   autogen-modules:  Paths_ede   other-modules:    Paths_ede @@ -62,6 +62,7 @@     Text.EDE     Text.EDE.Filters     Text.EDE.Internal.AST+    Text.EDE.Internal.Compat     Text.EDE.Internal.Eval     Text.EDE.Internal.Filters     Text.EDE.Internal.Parser@@ -70,8 +71,8 @@     Text.EDE.Internal.Types    build-depends:-    , aeson                        >=0.7-    , bytestring                   >=0.9+    , aeson                        >=1.4+    , bytestring                   >=0.10.4     , comonad                      >=4.2     , directory                    >=1.2     , filepath                     >=1.2@@ -79,7 +80,7 @@     , lens                         >=4.0     , mtl                          >=2.1.3.1     , parsers                      >=0.12.1.1-    , prettyprinter                >=1.6+    , prettyprinter                >=1.7     , prettyprinter-ansi-terminal  >=1.1     , scientific                   >=0.3.1     , text                         >=1.2@@ -94,14 +95,15 @@   main-is:        Main.hs   ghc-options:    -threaded -rtsopts -with-rtsopts=-A128m   build-depends:-    , aeson                        >=0.8-    , attoparsec+    , aeson                        >=1.4+    , attoparsec                   >=0.13     , bytestring                   >=0.10.4     , ede     , optparse-applicative         >=0.11-    , prettyprinter                >=1.6+    , prettyprinter                >= 1.7     , prettyprinter-ansi-terminal  >=1.1     , text                         >=1.2+    , unordered-containers         >=0.2.3  test-suite tests   import:         base
lib/Text/EDE.hs view
@@ -114,7 +114,7 @@  import qualified Control.Monad as Monad import Data.Aeson ((.=))-import Data.Aeson.Types (Object)+import Data.Aeson.Types (Value) import Data.ByteString (ByteString) import qualified Data.ByteString as ByteString import qualified Data.Foldable as Foldable@@ -125,9 +125,9 @@ import qualified Data.Text as Text import qualified Data.Text.Lazy as Text.Lazy import qualified Data.Text.Lazy.Builder as Text.Builder-import Data.Text.Prettyprint.Doc (Pretty (..)) import Data.Version (Version) import qualified Paths_ede as Paths+import Prettyprinter (Pretty (..)) import qualified System.Directory as Directory import qualified System.FilePath as FilePath import qualified Text.EDE.Internal.Eval as Eval@@ -270,23 +270,23 @@     then failure ("file " <> pretty path <> " doesn't exist.")     else ByteString.readFile path >>= success --- | Render an 'Object' using the supplied 'Template'.+-- | Render an 'HashMap Text Value' using the supplied 'Template'. render ::   -- | Parsed 'Template' to render.   Template ->   -- | Bindings to make available in the environment.-  Object ->+  HashMap Text Value ->   Result Text.Lazy.Text render = renderWith mempty --- | Render an 'Object' using the supplied 'Template'.+-- | Render an 'HashMap Text Value' using the supplied 'Template'. renderWith ::   -- | Filters to make available in the environment.   HashMap Id Term ->   -- | Parsed 'Template' to render.   Template ->   -- | Bindings to make available in the environment.-  Object ->+  HashMap Text Value ->   Result Text.Lazy.Text renderWith fs (Template _ u ts) =   fmap Text.Builder.toLazyText . Eval.render ts fs u@@ -312,7 +312,7 @@ -- | /See:/ 'render' eitherRender ::   Template ->-  Object ->+  HashMap Text Value ->   Either String Text.Lazy.Text eitherRender t = eitherResult . render t @@ -320,7 +320,7 @@ eitherRenderWith ::   HashMap Id Term ->   Template ->-  Object ->+  HashMap Text Value ->   Either String Text.Lazy.Text eitherRenderWith fs t = eitherResult . renderWith fs t @@ -333,15 +333,15 @@ -- -- >>> tmpl <- parse "{% if var %}\nHello, {{ var }}!\n{% else %}\nnegative!\n{% endif %}\n" :: Result Template ----- Then an 'Object' is defined containing the environment which will be+-- Then an 'HashMap Text Value' is defined containing the environment which will be -- available to the 'Template' during rendering: ----- >>> let env = fromPairs [ "var" .= "World" ] :: Object+-- >>> let env = fromPairs [ "var" .= "World" ] :: HashMap Text Value -- -- Note: the 'fromPairs' function above is a wrapper over Aeson's 'object'--- which removes the outer 'Object' 'Value' constructor, exposing the underlying 'HashMap'.+-- which removes the outer 'Data.Aeson.Object' 'Value' constructor, exposing the underlying 'HashMap'. ----- Then, the 'Template' is rendered using the 'Object' environment:+-- Then, the 'Template' is rendered using the 'HashMap Text Value' environment: -- -- >>> render tmpl env :: Result Text -- > Success "Hello, World!"@@ -379,7 +379,7 @@ -- which can be cached for future use. -- -- * Rendering takes a 'HashMap' of custom 'Fun's (functions available in the--- template context), an 'Object' as the binding environment, and a parsed+-- template context), an 'HashMap Text Value' as the binding environment, and a parsed -- 'Template' to subsitute the values into. -- The result is a Lazy 'Text.Lazy.Text' value containing the rendered output. @@ -487,12 +487,12 @@ -- -- Variables are substituted directly for their renderable representation. -- An error is raised if the varaible being substituted is not a literal type--- (ie. an 'Array' or 'Object') or doesn't exist in the supplied environment.+-- (ie. an 'Array' or 'HashMap Text Value') or doesn't exist in the supplied environment. -- -- > {{ var }} ----- Nested variable access is also supported for variables which resolve to an 'Object'.--- Dot delimiters are used to chain access through multiple nested 'Object's.+-- Nested variable access is also supported for variables which resolve to an 'HashMap Text Value'.+-- Dot delimiters are used to chain access through multiple nested 'HashMap Text Value's. -- The right-most accessor must resolve to a renderable type as with the previous -- non-nested variable access. --@@ -564,7 +564,7 @@  -- $loops ----- Iterating over an 'Array' or 'Object' can be acheived using the 'for ... in' section syntax.+-- Iterating over an 'Array' or 'HashMap Text Value' can be acheived using the 'for ... in' section syntax. -- Attempting to iterate over any other type will raise an error. -- -- Example:@@ -578,13 +578,13 @@ -- The iteration branch is rendering per item with the else branch being (which is optional) -- being rendered if the @{{ list }}@ variable is empty. ----- When iterating over an 'Object', a stable sort using key equivalence is applied, 'Array's+-- When iterating over an 'HashMap Text Value', a stable sort using key equivalence is applied, 'Array's -- are unmodified. -- -- The resulting binding within the iteration expression (in this case, @{{ var }}@) is--- an 'Object' containing the following keys:+-- an 'HashMap Text Value' containing the following keys: ----- * @key        :: Text@: They key if the loop target is an 'Object'+-- * @key        :: Text@: They key if the loop target is an 'HashMap Text Value' -- -- * @value      :: a@: The value of the loop target --@@ -620,8 +620,8 @@ -- Will render each item with its (1-based) loop index as a prefix, separated -- by a blank newline, without a trailing at the end of the document. ----- Valid loop targets are 'Object's, 'Array's, and 'String's, with only 'Object's--- having an available @{{ <var>.key }}@ in scope.+-- Valid loop targets are 'HashMap Text Value's, 'Array's, and 'String's, with+-- only 'HashMap Text Value's having an available @{{ <var>.key }}@ in scope.  -- $includes --
+ lib/Text/EDE/Internal/Compat.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE CPP #-}++-- |+-- Module      : Text.EDE.Internal.Eval+-- Copyright   : (c) 2022 Brendan Hay <brendan.g.hay@gmail.com>+-- License     : This Source Code Form is subject to the terms of+--               the Mozilla Public License, v. 2.0.+--               A copy of the MPL can be found in the LICENSE file or+--               you can obtain it at http://mozilla.org/MPL/2.0/.+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- /Warning/: this is an internal module, and does not have a stable+-- API or name. Functions in this module may not check or enforce+-- preconditions expected by public modules. Use at your own risk!+module Text.EDE.Internal.Compat+  ( toHashMapText,+    fromHashMapText,+  )+where++#if MIN_VERSION_aeson(2,0,0)+import Data.Aeson.KeyMap (toHashMapText, fromHashMapText)+#else+import Data.HashMap.Strict (HashMap)+import Data.Aeson.Types (Value)+import Data.Text (Text)++toHashMapText :: HashMap Text Value -> HashMap Text Value+toHashMapText = id++fromHashMapText :: HashMap Text Value -> HashMap Text Value+fromHashMapText = id+#endif
lib/Text/EDE/Internal/Eval.hs view
@@ -26,20 +26,22 @@ import Control.Monad.Trans (lift) import Data.Aeson ((.=)) import qualified Data.Aeson as Aeson-import Data.Aeson.Types (Object, Value (..))+import Data.Aeson.Types (Value (..)) import qualified Data.Foldable as Foldable import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NonEmpty import Data.Scientific (isFloating)+import Data.Text (Text) import qualified Data.Text as Text import Data.Text.Lazy.Builder (Builder) import qualified Data.Text.Lazy.Builder as Text.Builder import Data.Text.Lazy.Builder.Scientific (FPFormat (Fixed), formatScientificBuilder) import Data.Text.Manipulate (toOrdinal)-import Data.Text.Prettyprint.Doc ((<+>))-import qualified Data.Text.Prettyprint.Doc as PP+import Prettyprinter ((<+>))+import qualified Prettyprinter as PP+import Text.EDE.Internal.Compat import Text.EDE.Internal.Filters (stdlib) import Text.EDE.Internal.Quoting import Text.EDE.Internal.Types@@ -171,13 +173,13 @@           <+> PP.brackets (pp (Text.intercalate "," $ HashMap.keys ts)) {-# INLINEABLE eval #-} -bind :: (Object -> Object) -> Context a -> Context a+bind :: (HashMap Text Value -> HashMap Text Value) -> Context a -> Context a bind f = Reader.withReaderT (\x -> x {_values = f (_values x)}) {-# INLINEABLE bind #-}  variable :: Delta -> Var -> Context Value variable d (Var is) =-  Reader.asks _values >>= go (NonEmpty.toList is) [] . Object+  Reader.asks _values >>= go (NonEmpty.toList is) [] . Object . fromHashMapText   where     go [] _ v = pure v     go (k : ks) r v = do@@ -189,8 +191,8 @@       where         cur = Var (k :| r) -        nest :: Value -> Context Object-        nest (Object o) = pure o+        nest :: Value -> Context (HashMap Text Value)+        nest (Object o) = pure (toHashMapText o)         nest x =           throwError d $             "variable"
lib/Text/EDE/Internal/Filters.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-}@@ -22,7 +23,7 @@ module Text.EDE.Internal.Filters where  import qualified Data.Aeson as Aeson-import Data.Aeson.Types (Array, Object, Value (..))+import Data.Aeson.Types (Value (..)) import qualified Data.Char as Char import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap@@ -33,9 +34,11 @@ import qualified Data.Text.Lazy as Text.Lazy import qualified Data.Text.Lazy.Encoding as Text.Lazy.Encoding import qualified Data.Text.Manipulate as Text.Manipulate-import Data.Text.Prettyprint.Doc ((<+>)) import qualified Data.Text.Unsafe as Text.Unsafe+import Data.Vector (Vector) import qualified Data.Vector as Vector+import Prettyprinter ((<+>))+import Text.EDE.Internal.Compat import Text.EDE.Internal.Quoting import Text.EDE.Internal.Types @@ -110,8 +113,8 @@       qlist1 "init" initT initV,       "at" @: (\x i -> x Vector.! i :: Value),       -- object-      "keys" @: (HashMap.keys :: Object -> [Text]),-      "elems" @: (HashMap.elems :: Object -> [Value]),+      "keys" @: (HashMap.keys :: HashMap Text Value -> [Text]),+      "elems" @: (HashMap.elems :: HashMap Text Value -> [Value]),       -- , "map"        @: undefined       -- , "filter"     @: undefined       -- , "zip"        @: undefined@@ -119,7 +122,7 @@        -- polymorphic       "show" @: (Text.Lazy.Encoding.decodeUtf8 . Aeson.encode :: Value -> Text.Lazy.Text),-      "singleton" @: (pure :: Value -> Vector.Vector Value)+      "singleton" @: (pure :: Value -> Vector Value)       -- FIXME: existence checks currently hardcoded into the evaluator:       -- "default"       -- "defined"@@ -146,7 +149,7 @@   (Quote a, Quote b) =>   Id ->   (Text -> a) ->-  (Array -> b) ->+  (Vector Value -> b) ->   (Id, Term) qlist1 k f g = (k,) . TLam $ \case   TVal (String t) -> pure . quote k 0 $ f t@@ -161,12 +164,12 @@   (Quote a, Quote b, Quote c) =>   Id ->   (Text -> a) ->-  (Object -> b) ->-  (Array -> c) ->+  (HashMap Text Value -> b) ->+  (Vector Value -> c) ->   (Id, Term) qcol1 k f g h = (k,) . TLam $ \case   TVal (String t) -> pure . quote k 0 $ f t-  TVal (Object o) -> pure . quote k 0 $ g o+  TVal (Object o) -> pure . quote k 0 $ g (toHashMapText o)   TVal (Array v) -> pure . quote k 0 $ h v   x ->     Failure $@@ -178,7 +181,7 @@ tailT = text Text.Unsafe.unsafeTail initT = text Text.init -headV, lastV, tailV, initV :: Array -> Value+headV, lastV, tailV, initV :: Vector Value -> Value headV = vec Vector.unsafeHead lastV = vec Vector.unsafeLast tailV = vec (Array . Vector.unsafeTail)@@ -187,7 +190,7 @@ text :: (Text -> Text) -> Text -> Value text f = String . safe mempty Text.null f -vec :: (Array -> Value) -> Array -> Value+vec :: (Vector Value -> Value) -> Vector Value -> Value vec = safe (Array Vector.empty) Vector.null  safe :: b -> (a -> Bool) -> (a -> b) -> a -> b
lib/Text/EDE/Internal/Parser.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -31,11 +30,11 @@ import Control.Comonad.Cofree (Cofree ((:<))) import Control.Lens ((%=)) import qualified Control.Lens as Lens-import Control.Monad (MonadPlus, void, unless)+import Control.Monad (MonadPlus, unless, void) import Control.Monad.State.Strict (MonadState, StateT) import qualified Control.Monad.State.Strict as State import Control.Monad.Trans (lift)-import Data.Aeson.Types (Array, Object, Value (..))+import Data.Aeson.Types (Value (..)) import qualified Data.Bifunctor as Bifunctor import Data.ByteString (ByteString) import qualified Data.Char as Char@@ -48,8 +47,10 @@ import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text.Encoding+import Data.Vector (Vector) import qualified Data.Vector as Vector import Text.EDE.Internal.AST+import Text.EDE.Internal.Compat import Text.EDE.Internal.Syntax import Text.EDE.Internal.Types import qualified Text.Parser.Expression as Expression@@ -73,9 +74,7 @@  type Parser m =   ( Monad m,-#if MIN_VERSION_base(4,13,0)     MonadFail m,-#endif     MonadState Env m,     Trifecta.TokenParsing m,     Trifecta.DeltaParsing m,@@ -89,9 +88,7 @@       Applicative,       Alternative,       Monad,-#if MIN_VERSION_base(4,13,0)       MonadFail,-#endif       MonadPlus,       Trifecta.Parsing,       Trifecta.CharParsing,@@ -137,10 +134,11 @@ pragma :: Parser m => m () pragma =   void . Trifecta.many $ do-    !xs <- pragmal-      *> Trifecta.symbol "EDE_SYNTAX"-      *> Trifecta.sepBy field spaces-      <* trimr pragmar+    !xs <-+      pragmal+        *> Trifecta.symbol "EDE_SYNTAX"+        *> Trifecta.sepBy field spaces+        <* trimr pragmar      mapM_ (uncurry Lens.assign) xs   where@@ -194,7 +192,7 @@ block :: Parser m => String -> m a -> m a block k p =   Trifecta.try (multiLine (keyword k) p)-  <|> singleLine (keyword k) p+    <|> singleLine (keyword k) p  multiLine :: Parser m => m b -> m a -> m a multiLine s =@@ -342,7 +340,7 @@ collection = ann (EVar <$> variable <|> ELit <$> col)   where     col =-      Object <$> object+      (Object . fromHashMapText) <$> object         <|> Array <$> array         <|> String <$> Trifecta.stringLiteral @@ -351,7 +349,7 @@   Bool <$> bool     <|> Number <$> number     <|> String <$> Trifecta.stringLiteral-    <|> Object <$> object+    <|> (Object . fromHashMapText) <$> object     <|> Array <$> array  number :: Parser m => m Scientific@@ -364,7 +362,7 @@   Trifecta.symbol "true" *> pure True     <|> Trifecta.symbol "false" *> pure False -object :: Parser m => m Object+object :: Parser m => m (HashMap Text Value) object = HashMap.fromList <$> Trifecta.braces (Trifecta.commaSep pair)   where     pair =@@ -372,7 +370,7 @@         <$> (Trifecta.stringLiteral <* Trifecta.spaces)         <*> (Trifecta.char ':' *> Trifecta.spaces *> literal) -array :: Parser m => m Array+array :: Parser m => m (Vector Value) array = Vector.fromList <$> Trifecta.brackets (Trifecta.commaSep literal)  operator :: Parser m => Text -> m Delta@@ -413,10 +411,10 @@  triml :: Parser m => m a -> m a triml p = do-    c <- Trifecta.Delta.column <$> Trifecta.position-    if c == 0-        then Trifecta.spaces *> p-        else fail "left whitespace removal failed"+  c <- Trifecta.Delta.column <$> Trifecta.position+  if c == 0+    then Trifecta.spaces *> p+    else fail "left whitespace removal failed"  trimr :: Parser m => m a -> m a trimr p = p <* Trifecta.newline -- <* Trifecta.newline
lib/Text/EDE/Internal/Quoting.hs view
@@ -1,5 +1,5 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -26,9 +26,10 @@ import Control.Monad ((>=>)) import Data.Aeson (FromJSON, ToJSON) import qualified Data.Aeson as Aeson-import Data.Aeson.Types (Array, Object, Value (..))+import Data.Aeson.Types (Value (..)) import qualified Data.Bifunctor as Bifunctor import qualified Data.ByteString.Char8 as ByteString.Char8+import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import Data.List (sortBy) import Data.Ord (comparing)@@ -41,15 +42,18 @@ import Data.Text.Lazy.Builder (Builder) import qualified Data.Text.Lazy.Builder as Text.Builder import Data.Text.Manipulate (toOrdinal)-import Data.Text.Prettyprint.Doc (Pretty (..), (<+>))-import qualified Data.Text.Prettyprint.Doc as PP+import Data.Vector (Vector) import qualified Data.Vector as Vector+import Prettyprinter (Pretty (..), (<+>))+import qualified Prettyprinter as PP import Text.EDE.Internal.Types import Text.Trifecta.Delta (Delta) import qualified Text.Trifecta.Delta as Trifecta.Delta import qualified Text.Trifecta.Rendering as Trifecta.Rendering -default (AnsiDoc, Double, Integer)+#if MIN_VERSION_aeson(2,0,0)+import Data.Aeson.KeyMap (KeyMap)+#endif  -- | A HOAS representation of (possibly partially applied) values -- in the environment.@@ -96,6 +100,14 @@  instance Unquote Value +#if MIN_VERSION_aeson(2,0,0)+instance Unquote (KeyMap Value)+#endif++instance Unquote (HashMap Text Value)++instance Unquote (Vector Value)+ instance Unquote Text  instance Unquote [Text]@@ -108,10 +120,6 @@  instance Unquote Scientific -instance Unquote Object--instance Unquote Array- instance Unquote Int where   unquote k n =     unquote k n@@ -164,6 +172,14 @@  instance Quote Value +#if MIN_VERSION_aeson(2,0,0)+instance Quote (KeyMap Value)+#endif++instance Quote (HashMap Text Value)++instance Quote (Vector Value)+ instance Quote [Value]  instance Quote Text@@ -181,10 +197,6 @@ instance Quote Double  instance Quote Scientific--instance Quote Object--instance Quote Array  instance Quote Builder where   quote k n = quote k n . Text.Builder.toLazyText
lib/Text/EDE/Internal/Types.hs view
@@ -30,7 +30,7 @@ import Control.Comonad.Cofree (Cofree) import qualified Control.Lens as Lens import qualified Data.Aeson as Aeson-import Data.Aeson.Types (Object, Pair, Value (..))+import Data.Aeson.Types (Pair, Value (..)) import qualified Data.Functor.Classes as Functor.Classes import Data.HashMap.Strict (HashMap) import qualified Data.List as List@@ -38,9 +38,10 @@ import qualified Data.List.NonEmpty as NonEmpty import Data.Text (Text) import qualified Data.Text as Text-import Data.Text.Prettyprint.Doc (Doc, Pretty (..))-import qualified Data.Text.Prettyprint.Doc as PP-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as PP+import Prettyprinter (Doc, Pretty (..))+import qualified Prettyprinter as PP+import qualified Prettyprinter.Render.Terminal as PP+import Text.EDE.Internal.Compat import Text.Trifecta.Delta (Delta, HasDelta) import qualified Text.Trifecta.Delta as Trifecta.Delta @@ -86,7 +87,7 @@ $(Lens.makePrisms ''Result)  instance Monad Result where-  return = Success+  return = pure   {-# INLINE return #-}    Success x >>= k = k x@@ -94,7 +95,7 @@   {-# INLINE (>>=) #-}  instance Applicative Result where-  pure = return+  pure = Success   {-# INLINE pure #-}    Success f <*> Success x = Success (f x)@@ -228,15 +229,15 @@ -- | Unwrap a 'Value' to an 'Object' safely. -- -- See Aeson\'s documentation for more details.-fromValue :: Value -> Maybe Object-fromValue (Object o) = Just o+fromValue :: Value -> Maybe (HashMap Text Value)+fromValue (Object o) = Just (toHashMapText o) fromValue _ = Nothing  -- | Create an 'Object' from a list of name/value 'Pair's. -- -- See Aeson\'s documentation for more details.-fromPairs :: [Pair] -> Object+fromPairs :: [Pair] -> HashMap Text Value fromPairs xs =   case Aeson.object xs of-    Object o -> o+    Object o -> toHashMapText o     _other -> mempty