Skip to content

Instantly share code, notes, and snippets.

@peterszerzo
Last active October 8, 2019 17:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterszerzo/a93ad31977b4bc467a17eccc8382110e to your computer and use it in GitHub Desktop.
Save peterszerzo/a93ad31977b4bc467a17eccc8382110e to your computer and use it in GitHub Desktop.
module Main exposing (main)
import Browser
import Dict
import Html exposing (..)
import Html.Events exposing (onClick)
import Mark
-- Entry point
main : Program () Model Msg
main =
Browser.sandbox
{ init =
{ values = Dict.empty
}
, view = view
, update = update
}
-- Model
type alias Model =
{ values : Values
}
-- Values
type alias Values =
Dict.Dict String Float
getValue : String -> Values -> Float
getValue name values =
values
|> Dict.get name
-- Values that are not kept track of yet are assumed to be the default
|> Maybe.withDefault 0
-- Update
type Msg
= SetValue ( String, Float )
update : Msg -> Model -> Model
update msg model =
case msg of
SetValue ( key, val ) ->
{ model
| values =
Dict.insert key
val
model.values
}
-- View
view : Model -> Html Msg
view model =
case compileMarkup markup of
-- The success case yields a function that takes the current `Values` dictionary
Ok viewByData ->
viewByData model.values
-- Map to the program message
|> map SetValue
Err err ->
text err
markup : String
markup =
"""
|> Title
Interactive counteradder
|> Counter
name = var1
|> Counter
name = var2
|> Sum
arg1 = var1
arg2 = var2
"""
compileMarkup : String -> Result String (Values -> Html ( String, Float ))
compileMarkup markdownBody =
Mark.compile
(Mark.document
identity
(Mark.manyOf
[ titleBlock
, counterBlock
, sumBlock
]
)
)
markdownBody
|> (\res ->
case res of
Mark.Success blocks ->
Ok
(\data ->
div []
(List.map
-- Inject data into each block
-- This makes them into regular `elm-html` nodes
(\block -> block data)
blocks
)
)
_ ->
Err "Compile error"
)
-- Markup blocks
{-| Title block, renders to h1 [][ text _ ]
-}
titleBlock : Mark.Block (Values -> Html msg)
titleBlock =
Mark.block "Title"
(\str _ ->
h1 [] [ text str ]
)
Mark.string
{-| Counter block, renders to `var = [+] value [-]`
-}
counterBlock : Mark.Block (Values -> Html ( String, Float ))
counterBlock =
Mark.record "Counter"
(\name values ->
let
value =
getValue name values
in
div
[]
[ text (name ++ " = ")
, button
[ onClick ( name, value - 1 )
]
[ text "-"
]
, text (String.fromFloat value)
, button
[ onClick ( name, value + 1 )
]
[ text "+"
]
]
)
|> Mark.field "name" Mark.string
|> Mark.toBlock
{-| Renders the sum of two values controlled through counters, renders to `var1 + var2 == value`
-}
sumBlock : Mark.Block (Values -> Html ( String, Float ))
sumBlock =
Mark.record "Sum"
(\arg1 arg2 values ->
let
res =
getValue arg1 values + getValue arg2 values
in
div
[]
[ text (arg1 ++ " + " ++ arg2 ++ " == ")
, text (String.fromFloat res)
]
)
|> Mark.field "arg1" Mark.string
|> Mark.field "arg2" Mark.string
|> Mark.toBlock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment