jamesgary / elm-config-ui / ConfigFormGenerator

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

How to automate with a watcher script

#!/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

(use --save-dev instead of --global if you only need it locally for one project)

npm install --global elm elm-live


type Kind
    = IntKind String
    | FloatKind String
    | StringKind String
    | BoolKind String
    | ColorKind String
    | SectionKind

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.