Imagine being able to add a field to the config form with just one line! It can be done if you use code generation.
Use ConfigFormGenerator
in your ConfigSchema.elm
to make a Config.elm
file (it can be excluded from your src/
directory if you want, since it won't be compiled directly with your other elm files):
-- ConfigSchema.elm
import ConfigFormGenerator exposing (Kind(..))
import Html exposing (Html)
myConfigFields : List ( String, Kind )
myConfigFields =
[ ( "Header Font Size", IntKind "headerFontSize" )
, ( "Body Font Size", IntKind "bodyFontSize" )
, ( "Background Color", ColorKind "bgColor" )
]
main : Html msg
main =
let
generatedElmCode =
ConfigFormGenerator.toFile myConfigFields
_ =
Debug.log generatedElmCode ""
in
Html.text ""
When compiled, it makes an elm app whose sole purpose is to console.log
the elm code needed for a Config.elm
file. To generate it, run something like this:
# Compile schema file to tmp js:
elm make ConfigSchema.elm --output=~/tmp/tmp.js > /dev/null
# Run compiled js with node, which logs out generated elm code, and save to Config.elm:
node ~/tmp/tmp.js > Config.elm 2>/dev/null
#!/bin/bash
CONFIG_SCHEMA_ELMFILE=ConfigSchema.elm
CONFIG_ELMFILE=Config.elm
TMP_JS=~/tmp/gen-config.js
MAIN_ELMFILE=Main.elm
SERVER_DIR=public/
MAIN_JS_OUTPUT=public/js/main.js
GENERATE_ARGS="$CONFIG_SCHEMA_ELMFILE $TMP_JS $CONFIG_ELMFILE"
# Command for generating Config.elm from ConfigSchema.elm
generate_config () {
CONFIG_SCHEMA_ELMFILE=$1
TMP_JS=$2
CONFIG_ELMFILE=$3
# Use `elm make` to make an elm app that console.logs the generated Config.elm code
elm make $CONFIG_SCHEMA_ELMFILE --output=$TMP_JS > /dev/null && \
# Run it with `node` to print the output and write to Config.elm
node $TMP_JS > $CONFIG_ELMFILE 2>/dev/null
}
export -f generate_config
# Generate the config initially, just in case it doesn't exist
generate_config $GENERATE_ARGS
# Watch for config changes
chokidar $CONFIG_SCHEMA_ELMFILE --command "generate_config $GENERATE_ARGS" &
# Watch for elm changes
elm-live $MAIN_ELMFILE --dir=$SERVER_DIR -- --output=$MAIN_JS_OUTPUT &
wait
This will watch for changes to ConfigSchema.elm
and generate a Config.elm
file. Make sure you have the following installed, too:
```shell
npm install --global elm elm-live
Use these to define what kind of value your field is. For all values except SectionKind
, the String
is the field's camelCase variable name for both your Config
record and its JSON representation, such as "headerFontSize".
SectionKind
is just for visually organizing your fields.
toFile : List ( String, Kind ) -> String
Generates the elm code for your Config module given a list of labels and field kinds.