Add Haste driver and launcher and beginning of HTML demo.
Chris Pressey
3 years ago
10 | 10 | |
11 | 11 | # For this to work, you need hastec installed. |
12 | 12 | |
13 | if command -v hastec_not_now_murray_not_now >/dev/null 2>&1; then | |
13 | if command -v hastec >/dev/null 2>&1; then | |
14 | 14 | echo "building $PROG.js with hastec" |
15 | 15 | (cd src && hastec --make HasteMain.hs -o ../demo/$PROG.js) |
16 | 16 | else |
0 | function launch(config) { | |
1 | config.container.innerHTML = ` | |
2 | <textarea id="prog" rows="10" cols="80"></textarea> | |
3 | <div id="control-panel"></div> | |
4 | <div>Input: <input id="prog-input"></input></div> | |
5 | <div>Output: <pre id="prog-output"></pre></div> | |
6 | <div><button id="run-button">Run</button></div> | |
7 | <pre id="result"></pre> | |
8 | `; | |
9 | ||
10 | function makeSelect(container, labelText, optionsArray, fun) { | |
11 | var label = document.createElement('label'); | |
12 | label.innerHTML = labelText; | |
13 | container.appendChild(label); | |
14 | var select = document.createElement("select"); | |
15 | for (var i = 0; i < optionsArray.length; i++) { | |
16 | var op = document.createElement("option"); | |
17 | op.text = optionsArray[i].filename; | |
18 | op.value = optionsArray[i].contents; | |
19 | select.options.add(op); | |
20 | } | |
21 | select.onchange = function(e) { | |
22 | fun(optionsArray[select.selectedIndex]); | |
23 | }; | |
24 | select.selectedIndex = 0; | |
25 | label.appendChild(select); | |
26 | return select; | |
27 | }; | |
28 | ||
29 | function selectOptionByText(selectElem, text) { | |
30 | var optElem; | |
31 | for (var i = 0; optElem = selectElem.options[i]; i++) { | |
32 | if (optElem.text === text) { | |
33 | selectElem.selectedIndex = i; | |
34 | selectElem.dispatchEvent(new Event('change')); | |
35 | return; | |
36 | } | |
37 | } | |
38 | } | |
39 | ||
40 | var controlPanel = document.getElementById('control-panel'); | |
41 | var select = makeSelect(controlPanel, "example program:", examplePrograms, function(option) { | |
42 | document.getElementById('prog').value = option.contents; | |
43 | }); | |
44 | selectOptionByText(select, config.initialOption); | |
45 | } |
0 | <!DOCTYPE html> | |
1 | <head> | |
2 | <meta charset="utf-8"> | |
3 | <title>Mascarpone</title> | |
4 | </head> | |
5 | <body> | |
6 | ||
7 | <h1>Mascarpone</h1> | |
8 | ||
9 | <p>(Mascarpone.hs compiled to .js by <code>hastec</code>, running in HTML5 document)</p> | |
10 | ||
11 | <div id="installation"></div> | |
12 | ||
13 | <script src="../eg/examplePrograms.jsonp.js"></script> | |
14 | <script src="hastec-io-launcher.js"></script> | |
15 | <script src="mascarpone.js"></script> | |
16 | <script> | |
17 | launch({ | |
18 | container: document.getElementById('installation'), | |
19 | initialOption: "hello.emmental" | |
20 | }); | |
21 | </script> | |
22 | </body> |
0 | {-# LANGUAGE OverloadedStrings #-} | |
1 | ||
2 | module Main where | |
3 | ||
4 | import Haste.DOM (withElems, getValue, setProp) | |
5 | import Haste.Events (onEvent, MouseEvent(Click)) | |
6 | import Haste.Foreign (ffi) | |
7 | ||
8 | import Language.Mascarpone (getStack, mascarponeWithIO) | |
9 | ||
10 | ||
11 | getCh :: IO Char | |
12 | getCh = ffi "(function() {var i=document.getElementById('prog-input'); var s=i.value; i.value=s.substring(1); return s.charCodeAt(0);})" | |
13 | ||
14 | putCh :: Char -> IO () | |
15 | putCh = ffi "(function(c) {var o=document.getElementById('prog-output'); o.textContent += String.fromCharCode(c);})" | |
16 | ||
17 | clearOutput :: IO () | |
18 | clearOutput = ffi "(function(c) {var o=document.getElementById('prog-output'); o.textContent = '';})" | |
19 | ||
20 | main = withElems ["prog", "result", "run-button"] driver | |
21 | ||
22 | driver [progElem, resultElem, runButtonElem] = | |
23 | onEvent runButtonElem Click $ \_ -> do | |
24 | Just prog <- getValue progElem | |
25 | clearOutput | |
26 | r <- mascarponeWithIO (getCh) (putCh) prog | |
27 | setProp resultElem "textContent" $ show $ getStack $ r |