+:root {
+ --menu-bar-height: 32px;
+}
+
* {
margin: 0;
padding: 0;
overflow: hidden;
}
+select {
+ margin: calc((var(--menu-bar-height) - 24px) / 2);
+ height: 24px;
+ min-width: 64px;
+
+ border: none;
+ color: white;
+ background: #222;
+
+ transition: all 0.5s;
+}
+
+select:hover {
+ background: #444;
+ cursor: pointer;
+}
+
+button {
+ margin: calc((var(--menu-bar-height) - 24px) / 2);
+ height: 24px;
+ min-width: 64px;
+
+ border: none;
+ color: white;
+ background: #222;
+
+ transition: all 0.5s;
+}
+
+button:hover {
+ background: #444;
+ cursor: pointer;
+}
+
.left-half, .right-half {
width: 50%;
height: 100%;
}
.top-half {
- height: 24px;
+ height: var(--menu-bar-height);
}
.bottom-half {
- height: calc(100% - 24px);
+ height: calc(100% - var(--menu-bar-height));
}
#code-editor {
#code-result {
height: 100%;
- max-height: 100%;
+ max-height: calc(100% - 24px); /* subtract the padding */
background: #000;
color: #fff;
font-size: 16px;
overflow-y: auto;
overflow-x: auto;
+
+ padding: 12px;
}
let wasm_worker = null;
-
-function update_running_msg() {
- let elem = document.getElementById('running-msg');
- if (wasm_worker == null) {
- elem.innerHTML = "";
-
- } else {
- elem.innerHTML = "Running...";
- }
-}
-
-function change_editor_theme() {
- let editor = ace.edit('code-editor');
- let elem = document.getElementById('code-editor-theme');
-
- editor.setTheme(`ace/theme/${elem.value}`);
-}
+let editor_keybind_mode = "normal";
+let editor_theme = "chrome";
async function clear_output() {
let elem = document.getElementById('code-result');
update_running_msg();
}
+function update_running_msg() {
+ let elem = document.getElementById('running-msg');
+ if (wasm_worker == null) {
+ elem.innerHTML = "";
+
+ } else {
+ elem.innerHTML = "Running...";
+ }
+}
+
+function change_editor_theme(value) {
+ let editor = ace.edit('code-editor');
+ let elem = document.getElementById('code-editor-theme');
+
+ if (value == null) {
+ value = elem.value;
+ } else {
+ document.querySelector(`#code-editor-theme option[value="${value}"]`).selected = true;
+ }
+
+ editor.setTheme(`ace/theme/${value}`);
+
+ editor_theme = value;
+ persist_settings();
+}
+
+function change_keybindings(value) {
+ let editor = ace.edit('code-editor');
+ let elem = document.getElementById('code-editor-keybindings');
+
+ if (value == null) {
+ value = elem.value;
+ } else {
+ document.querySelector(`#code-editor-keybindings option[value="${value}"]`).selected = true;
+ }
+
+ if (value == "normal") editor.setKeyboardHandler("");
+ else editor.setKeyboardHandler(`ace/keyboard/${value}`);
+
+ editor_keybind_mode = value;
+ persist_settings();
+}
+
+function persist_settings() {
+ localStorage["editor_theme"] = editor_theme;
+ localStorage["editor_keybind_mode"] = editor_keybind_mode;
+}
+
+function load_settings() {
+ editor_theme = localStorage["editor_theme"];
+ editor_keybind_mode = localStorage["editor_keybind_mode"];
+
+ change_editor_theme(editor_theme);
+ change_keybindings(editor_keybind_mode);
+}
+
window.onload = () => {
let editor = ace.edit('code-editor');
editor.setShowPrintMargin(false);
editor.setFontSize(16);
editor.session.setMode('ace/mode/onyx');
- editor.setKeyboardHandler("ace/keyboard/vim");
+
+ load_settings();
};
--- /dev/null
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright 2011 Irakli Gozalishvili. All rights reserved.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ * ***** END LICENSE BLOCK ***** */
+
+define("ace/theme/github",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
+
+exports.isDark = true;
+exports.cssClass = "ace-gruvbox";
+exports.cssText = `.ace-gruvbox .ace_gutter-active-line {
+ background-color: #3C3836;
+}
+
+.ace-gruvbox {
+ color: #EBDAB4;
+ background-color: #1D2021;
+}
+
+.ace-gruvbox .ace_invisible {
+ color: #504945;
+}
+
+.ace-gruvbox .ace_marker-layer .ace_selection {
+ background: rgba(179, 101, 57, 0.75)
+}
+
+.ace-gruvbox.ace_multiselect .ace_selection.ace_start {
+ box-shadow: 0 0 3px 0px #002240;
+}
+
+.ace-gruvbox .ace_keyword {
+ color: #8ec07c;
+}
+
+.ace-gruvbox .ace_comment {
+ font-style: italic;
+ color: #928375;
+}
+
+.ace-gruvbox .ace-statement {
+ color: red;
+}
+
+.ace-gruvbox .ace_variable {
+ color: #84A598;
+}
+
+.ace-gruvbox .ace_variable.ace_language {
+ color: #D2879B;
+}
+
+.ace-gruvbox .ace_constant {
+ color: #C2859A;
+}
+
+.ace-gruvbox .ace_constant.ace_language {
+ color: #C2859A;
+}
+
+.ace-gruvbox .ace_constant.ace_numeric {
+ color: #C2859A;
+}
+
+.ace-gruvbox .ace_string {
+ color: #B8BA37;
+}
+
+.ace-gruvbox .ace_support {
+ color: #F9BC41;
+}
+
+.ace-gruvbox .ace_support.ace_function {
+ color: #F84B3C;
+}
+
+.ace-gruvbox .ace_storage {
+ color: #8FBF7F;
+}
+
+.ace-gruvbox .ace_keyword.ace_operator {
+ color: #EBDAB4;
+}
+
+.ace-gruvbox .ace_punctuation.ace_operator {
+ color: yellow;
+}
+
+.ace-gruvbox .ace_marker-layer .ace_active-line {
+ background: #3C3836;
+}
+
+.ace-gruvbox .ace_marker-layer .ace_selected-word {
+ border-radius: 4px;
+ border: 8px solid #3f475d;
+}
+
+.ace-gruvbox .ace_print-margin {
+ width: 5px;
+ background: #3C3836;
+}
+
+.ace-gruvbox .ace_indent-guide {
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQUFD4z6Crq/sfAAuYAuYl+7lfAAAAAElFTkSuQmCC") right repeat-y;
+}
+`;
+
+var dom = require("../lib/dom");
+dom.importCssString(exports.cssText, exports.cssClass);
+
+});
+
+ (function() {
+ window.require(["ace/theme/github"], function(m) {
+ if (typeof module == "object" && typeof exports == "object" && module) {
+ module.exports = m;
+ }
+ });
+ })();
+
--- /dev/null
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2010, Ajax.org B.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Ajax.org B.V. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define("ace/theme/monokai", ["require","exports","module","ace/lib/dom"], function(require, exports, module) {
+ exports.isDark = true;
+ exports.cssClass = "ace-monokai";
+ exports.cssText = `.ace-monokai .ace_gutter {
+ background: #2F3129;
+ color: #8F908A
+}
+
+.ace-monokai .ace_print-margin {
+ width: 1px;
+ background: #555651
+}
+
+.ace-monokai {
+ background-color: #272822;
+ color: #F8F8F2
+}
+
+.ace-monokai .ace_cursor {
+ color: #F8F8F0
+}
+
+.ace-monokai .ace_marker-layer .ace_selection {
+ background: #49483E
+}
+
+.ace-monokai.ace_multiselect .ace_selection.ace_start {
+ box-shadow: 0 0 3px 0px #272822;
+}
+
+.ace-monokai .ace_marker-layer .ace_step {
+ background: rgb(102, 82, 0)
+}
+
+.ace-monokai .ace_marker-layer .ace_bracket {
+ margin: -1px 0 0 -1px;
+ border: 1px solid #49483E
+}
+
+.ace-monokai .ace_marker-layer .ace_active-line {
+ background: #202020
+}
+
+.ace-monokai .ace_gutter-active-line {
+ background-color: #272727
+}
+
+.ace-monokai .ace_marker-layer .ace_selected-word {
+ border: 1px solid #49483E
+}
+
+.ace-monokai .ace_invisible {
+ color: #52524d
+}
+
+.ace-monokai .ace_entity.ace_name.ace_tag,
+.ace-monokai .ace_keyword,
+.ace-monokai .ace_meta.ace_tag,
+.ace-monokai .ace_storage {
+ color: #F92672
+}
+
+.ace-monokai .ace_punctuation,
+.ace-monokai .ace_punctuation.ace_tag {
+ color: #fff
+}
+
+.ace-monokai .ace_constant.ace_character,
+.ace-monokai .ace_constant.ace_language,
+.ace-monokai .ace_constant.ace_numeric,
+.ace-monokai .ace_constant.ace_other {
+ color: #AE81FF
+}
+
+.ace-monokai .ace_invalid {
+ color: #F8F8F0;
+ background-color: #F92672
+}
+
+.ace-monokai .ace_invalid.ace_deprecated {
+ color: #F8F8F0;
+ background-color: #AE81FF
+}
+
+.ace-monokai .ace_support.ace_constant,
+.ace-monokai .ace_support.ace_function {
+ color: #66D9EF
+}
+
+.ace-monokai .ace_fold {
+ background-color: #A6E22E;
+ border-color: #F8F8F2
+}
+
+.ace-monokai .ace_storage.ace_type,
+.ace-monokai .ace_support.ace_class,
+.ace-monokai .ace_support.ace_type {
+ font-style: italic;
+ color: #66D9EF
+}
+
+.ace-monokai .ace_entity.ace_name.ace_function,
+.ace-monokai .ace_entity.ace_other,
+.ace-monokai .ace_entity.ace_other.ace_attribute-name,
+.ace-monokai .ace_variable {
+ color: #A6E22E
+}
+
+.ace-monokai .ace_variable.ace_parameter {
+ font-style: italic;
+ color: #FD971F
+}
+
+.ace-monokai .ace_string {
+ color: #E6DB74
+}
+
+.ace-monokai .ace_comment {
+ color: #75715E
+}
+
+.ace-monokai .ace_indent-guide {
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y
+}`;
+
+
+ var dom = require("../lib/dom");
+ dom.importCssString(exports.cssText, exports.cssClass);
+});
+
+ (function() {
+ window.require(["ace/theme/monokai"], function(m) {
+ if (typeof module == "object" && typeof exports == "object" && module) {
+ module.exports = m;
+ }
+ });
+ })();
+
--- /dev/null
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2010, Ajax.org B.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Ajax.org B.V. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define("ace/theme/tomorrow-night-bright",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
+
+exports.isDark = true;
+exports.cssClass = "ace-tomorrow-night-bright";
+exports.cssText = `.ace-tomorrow-night-bright .ace_gutter {
+ background: #1a1a1a;
+ color: #DEDEDE
+}
+
+.ace-tomorrow-night-bright .ace_print-margin {
+ width: 1px;
+ background: #1a1a1a
+}
+
+.ace-tomorrow-night-bright {
+ background-color: #000000;
+ color: #DEDEDE
+}
+
+.ace-tomorrow-night-bright .ace_cursor {
+ color: #9F9F9F
+}
+
+.ace-tomorrow-night-bright .ace_marker-layer .ace_selection {
+ background: #424242
+}
+
+.ace-tomorrow-night-bright.ace_multiselect .ace_selection.ace_start {
+ box-shadow: 0 0 3px 0px #000000;
+}
+
+.ace-tomorrow-night-bright .ace_marker-layer .ace_step {
+ background: rgb(102, 82, 0)
+}
+
+.ace-tomorrow-night-bright .ace_marker-layer .ace_bracket {
+ margin: -1px 0 0 -1px;
+ border: 1px solid #888888
+}
+
+.ace-tomorrow-night-bright .ace_marker-layer .ace_highlight {
+ border: 1px solid rgb(110, 119, 0);
+ border-bottom: 0;
+ box-shadow: inset 0 -1px rgb(110, 119, 0);
+ margin: -1px 0 0 -1px;
+ background: rgba(255, 235, 0, 0.1)
+}
+
+.ace-tomorrow-night-bright .ace_marker-layer .ace_active-line {
+ background: #2A2A2A
+}
+
+.ace-tomorrow-night-bright .ace_gutter-active-line {
+ background-color: #2A2A2A
+}
+
+.ace-tomorrow-night-bright .ace_stack {
+ background-color: rgb(66, 90, 44)
+}
+
+.ace-tomorrow-night-bright .ace_marker-layer .ace_selected-word {
+ border: 1px solid #888888
+}
+
+.ace-tomorrow-night-bright .ace_invisible {
+ color: #343434
+}
+
+.ace-tomorrow-night-bright .ace_keyword,
+.ace-tomorrow-night-bright .ace_meta,
+.ace-tomorrow-night-bright .ace_storage,
+.ace-tomorrow-night-bright .ace_storage.ace_type,
+.ace-tomorrow-night-bright .ace_support.ace_type {
+ color: #C397D8
+}
+
+.ace-tomorrow-night-bright .ace_keyword.ace_operator {
+ color: #70C0B1
+}
+
+.ace-tomorrow-night-bright .ace_constant.ace_character,
+.ace-tomorrow-night-bright .ace_constant.ace_language,
+.ace-tomorrow-night-bright .ace_constant.ace_numeric,
+.ace-tomorrow-night-bright .ace_keyword.ace_other.ace_unit,
+.ace-tomorrow-night-bright .ace_support.ace_constant,
+.ace-tomorrow-night-bright .ace_variable.ace_parameter {
+ color: #E78C45
+}
+
+.ace-tomorrow-night-bright .ace_constant.ace_other {
+ color: #EEEEEE
+}
+
+.ace-tomorrow-night-bright .ace_invalid {
+ color: #CED2CF;
+ background-color: #DF5F5F
+}
+
+.ace-tomorrow-night-bright .ace_invalid.ace_deprecated {
+ color: #CED2CF;
+ background-color: #B798BF
+}
+
+.ace-tomorrow-night-bright .ace_fold {
+ background-color: #7AA6DA;
+ border-color: #DEDEDE
+}
+
+.ace-tomorrow-night-bright .ace_entity.ace_name.ace_function,
+.ace-tomorrow-night-bright .ace_support.ace_function,
+.ace-tomorrow-night-bright .ace_variable {
+ color: #7AA6DA
+}
+
+.ace-tomorrow-night-bright .ace_support.ace_class,
+.ace-tomorrow-night-bright .ace_support.ace_type {
+ color: #E7C547
+}
+
+.ace-tomorrow-night-bright .ace_heading,
+.ace-tomorrow-night-bright .ace_markup.ace_heading,
+.ace-tomorrow-night-bright .ace_string {
+ color: #B9CA4A
+}
+
+.ace-tomorrow-night-bright .ace_entity.ace_name.ace_tag,
+.ace-tomorrow-night-bright .ace_entity.ace_other.ace_attribute-name,
+.ace-tomorrow-night-bright .ace_meta.ace_tag,
+.ace-tomorrow-night-bright .ace_string.ace_regexp,
+.ace-tomorrow-night-bright .ace_variable {
+ color: #D54E53
+}
+
+.ace-tomorrow-night-bright .ace_comment {
+ color: #969896
+}
+
+.ace-tomorrow-night-bright .ace_c9searchresults.ace_keyword {
+ color: #C2C280
+}
+
+.ace-tomorrow-night-bright .ace_indent-guide {
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y
+}
+`;
+
+var dom = require("../lib/dom");
+dom.importCssString(exports.cssText, exports.cssClass);
+});
+ (function() {
+ window.require(["ace/theme/tomorrow-night-bright"], function(m) {
+ if (typeof module == "object" && typeof exports == "object" && module) {
+ module.exports = m;
+ }
+ });
+ })();
+
<body>
<div class="left-half">
<div class="top-half">
- <label for="editor-theme">Theme:</label>
- <select name="editor-theme" id="code-editor-theme" onchange="change_editor_theme()">
+ <select aria-label="Keybindings" name="keybindings" id="code-editor-keybindings" onchange="change_keybindings()">
+ <option value="normal">Normal</option>
+ <option value="vim">Vim</option>
+ <option value="emacs">Emacs</option>
+ <option value="sublime">Sublime Text</option>
+ <option value="vscode">VS Code</option>
+ </select>
+
+ <select aria-label="Theme" name="editor-theme" id="code-editor-theme" onchange="change_editor_theme()">
<option value="ambiance">Ambiance</option>
<option value="chaos">Chaos</option>
- <option selected value="chrome">Chrome</option>
+ <option value="chrome">Chrome</option>
<option value="clouds">Clouds</option>
+ <option value="github">Github</option>
+ <option selected value="monokai">Monokai</option>
+ <option value="tomorrow-night-bright">Tomorrow Night Bright</option>
</select>
+
+ <button onclick="submit_code()">Run</button>
+ <button onclick="kill_code()">Stop</button>
+
+ <span id="running-msg"></span>
</div>
<div class="bottom-half">
<div class="right-half">
<div class="top-half">
- <input type="button" value="Run" onclick="submit_code()" />
- <input type="button" value="Stop" onclick="kill_code()" />
-
- <span id="running-msg"></span>
</div>
<div class="bottom-half">