Add new --omitEmpty
option (#842)
... as proposed in https://github.com/dhall-lang/dhall-kubernetes/issues/46#issuecomment-468530601 `--omitEmpty` is the same as `--omitNull` except it also omits fields that are empty records. To be precise, it omits fields whose transitive fields are all `null` (and an empty record is a special case of a record whose transitive fields are all `null` since it is vacuously true when there are no fields). This allows Dhall configurations that target YAML to avoid having to nest sub-records inside of an `Optional` value. Omitting unnecessary `Optional` layers reduces the number of default values that the configuration format needs to thread around.
This commit is contained in:
parent
aa359813c4
commit
f6d6ccd0c5
|
@ -63,6 +63,7 @@ Executable dhall-to-yaml
|
|||
Main-Is: Main.hs
|
||||
Build-Depends:
|
||||
base ,
|
||||
aeson ,
|
||||
bytestring < 0.11,
|
||||
dhall ,
|
||||
dhall-json ,
|
||||
|
|
|
@ -6,6 +6,7 @@ module Main where
|
|||
import Control.Applicative ((<|>))
|
||||
import Control.Exception (SomeException)
|
||||
import Control.Monad (when)
|
||||
import Data.Aeson (Value)
|
||||
import Data.Monoid ((<>))
|
||||
import Data.Version (showVersion)
|
||||
import Dhall.JSON (Conversion)
|
||||
|
@ -28,7 +29,7 @@ import qualified System.IO
|
|||
data Options = Options
|
||||
{ explain :: Bool
|
||||
, pretty :: Bool
|
||||
, omitNull :: Bool
|
||||
, omission :: Value -> Value
|
||||
, version :: Bool
|
||||
, conversion :: Conversion
|
||||
}
|
||||
|
@ -38,7 +39,7 @@ parseOptions =
|
|||
Options
|
||||
<$> parseExplain
|
||||
<*> parsePretty
|
||||
<*> parseOmitNull
|
||||
<*> Dhall.JSON.parseOmission
|
||||
<*> parseVersion
|
||||
<*> Dhall.JSON.parseConversion
|
||||
where
|
||||
|
@ -68,12 +69,6 @@ parseOptions =
|
|||
defaultBehavior =
|
||||
pure False
|
||||
|
||||
parseOmitNull =
|
||||
Options.Applicative.switch
|
||||
( Options.Applicative.long "omitNull"
|
||||
<> Options.Applicative.help "Omit record fields that are null"
|
||||
)
|
||||
|
||||
parseVersion =
|
||||
Options.Applicative.switch
|
||||
( Options.Applicative.long "version"
|
||||
|
@ -111,11 +106,9 @@ main = do
|
|||
|
||||
let explaining = if explain then Dhall.detailed else id
|
||||
|
||||
let omittingNull = if omitNull then Dhall.JSON.omitNull else id
|
||||
|
||||
stdin <- Data.Text.IO.getContents
|
||||
|
||||
json <- omittingNull <$> explaining (Dhall.JSON.codeToValue conversion "(stdin)" stdin)
|
||||
json <- omission <$> explaining (Dhall.JSON.codeToValue conversion "(stdin)" stdin)
|
||||
|
||||
Data.ByteString.Char8.putStrLn $ Data.ByteString.Lazy.toStrict $ encode json
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module Main where
|
||||
|
||||
import Control.Exception (SomeException)
|
||||
import Data.Aeson (Value)
|
||||
import Data.Monoid ((<>))
|
||||
import Dhall.JSON (Conversion)
|
||||
import Options.Applicative (Parser, ParserInfo)
|
||||
|
@ -22,7 +23,7 @@ import qualified System.IO
|
|||
|
||||
data Options = Options
|
||||
{ explain :: Bool
|
||||
, omitNull :: Bool
|
||||
, omission :: Value -> Value
|
||||
, documents :: Bool
|
||||
, conversion :: Conversion
|
||||
}
|
||||
|
@ -31,7 +32,7 @@ parseOptions :: Parser Options
|
|||
parseOptions =
|
||||
Options
|
||||
<$> parseExplain
|
||||
<*> parseOmitNull
|
||||
<*> Dhall.JSON.parseOmission
|
||||
<*> parseDocuments
|
||||
<*> Dhall.JSON.parseConversion
|
||||
where
|
||||
|
@ -41,12 +42,6 @@ parseOptions =
|
|||
<> Options.Applicative.help "Explain error messages in detail"
|
||||
)
|
||||
|
||||
parseOmitNull =
|
||||
Options.Applicative.switch
|
||||
( Options.Applicative.long "omitNull"
|
||||
<> Options.Applicative.help "Omit record fields that are null"
|
||||
)
|
||||
|
||||
parseDocuments =
|
||||
Options.Applicative.switch
|
||||
( Options.Applicative.long "documents"
|
||||
|
@ -70,11 +65,9 @@ main = do
|
|||
handle $ do
|
||||
let explaining = if explain then Dhall.detailed else id
|
||||
|
||||
let omittingNull = if omitNull then Dhall.JSON.omitNull else id
|
||||
|
||||
stdin <- Data.Text.IO.getContents
|
||||
|
||||
json <- omittingNull <$> explaining (Dhall.JSON.codeToValue conversion "(stdin)" stdin)
|
||||
json <- omission <$> explaining (Dhall.JSON.codeToValue conversion "(stdin)" stdin)
|
||||
|
||||
let yaml = case (documents, json) of
|
||||
(True, Data.Yaml.Array elems)
|
||||
|
|
|
@ -161,6 +161,8 @@ module Dhall.JSON (
|
|||
-- * Dhall to JSON
|
||||
dhallToJSON
|
||||
, omitNull
|
||||
, omitEmpty
|
||||
, parseOmission
|
||||
, Conversion(..)
|
||||
, convertToHomogeneousMaps
|
||||
, parseConversion
|
||||
|
@ -329,8 +331,9 @@ toOrderedList =
|
|||
|
||||
-- | Omit record fields that are @null@
|
||||
omitNull :: Value -> Value
|
||||
omitNull (Object object) =
|
||||
Object (fmap omitNull (Data.HashMap.Strict.filter (/= Null) object))
|
||||
omitNull (Object object) = Object fields
|
||||
where
|
||||
fields =Data.HashMap.Strict.filter (/= Null) (fmap omitNull object)
|
||||
omitNull (Array array) =
|
||||
Array (fmap omitNull array)
|
||||
omitNull (String string) =
|
||||
|
@ -342,6 +345,40 @@ omitNull (Bool bool) =
|
|||
omitNull Null =
|
||||
Null
|
||||
|
||||
{-| Omit record fields that are @null@ or records whose transitive fields are
|
||||
all null
|
||||
-}
|
||||
omitEmpty :: Value -> Value
|
||||
omitEmpty (Object object) =
|
||||
if null fields then Null else Object fields
|
||||
where
|
||||
fields = Data.HashMap.Strict.filter (/= Null) (fmap omitEmpty object)
|
||||
omitEmpty (Array array) =
|
||||
Array (fmap omitEmpty array)
|
||||
omitEmpty (String string) =
|
||||
String string
|
||||
omitEmpty (Number number) =
|
||||
Number number
|
||||
omitEmpty (Bool bool) =
|
||||
Bool bool
|
||||
omitEmpty Null =
|
||||
Null
|
||||
|
||||
-- | Parser for command-line options related to omitting fields
|
||||
parseOmission :: Parser (Value -> Value)
|
||||
parseOmission =
|
||||
Options.Applicative.flag'
|
||||
omitNull
|
||||
( Options.Applicative.long "omitNull"
|
||||
<> Options.Applicative.help "Omit record fields that are null"
|
||||
)
|
||||
<|> Options.Applicative.flag'
|
||||
omitEmpty
|
||||
( Options.Applicative.long "omitEmpty"
|
||||
<> Options.Applicative.help "Omit record fields that are null or empty records"
|
||||
)
|
||||
<|> pure id
|
||||
|
||||
{-| Specify whether or not to convert association lists of type
|
||||
@List { mapKey: Text, mapValue : v }@ to records
|
||||
-}
|
||||
|
@ -691,6 +728,7 @@ convertToHomogeneousMaps (Conversion {..}) e0 = loop (Dhall.Core.normalize e0)
|
|||
Dhall.Core.Embed a ->
|
||||
Dhall.Core.Embed a
|
||||
|
||||
-- | Parser for command-line options related to homogeneous map support
|
||||
parseConversion :: Parser Conversion
|
||||
parseConversion =
|
||||
conversion
|
||||
|
|
Loading…
Reference in New Issue
Block a user