NDOJ/resources/ide.js
2022-02-20 19:33:35 -06:00

868 lines
No EOL
23 KiB
JavaScript

var wait = true;
var check_timeout = 300;
var editorMode = localStorageGetItem("editorMode") || "normal";
var redirectStderrToStdout = ((localStorageGetItem("redirectStderrToStdout") || "false") === "true");
var editorModeObject = null;
var fontSize = 14;
var MonacoVim;
var MonacoEmacs;
var layout;
var sourceEditor;
var stdinEditor;
var stdoutEditor;
var stderrEditor;
var isEditorDirty = false;
var currentLanguageId;
var $selectLanguage
var $selectTheme
var $insertTemplateBtn;
var $runBtn;
var timeStart;
var timeEnd;
var layoutConfig = {
settings: {
showPopoutIcon: false,
reorderEnabled: true
},
dimensions: {
borderWidth: 3,
headerHeight: 22
},
content: [{
type: "row",
content: [{
type: "component",
componentName: "source",
title: "SOURCE",
isClosable: false,
componentState: {
readOnly: false
},
width: 60
}, {
type: "column",
content: [{
type: "stack",
content: [{
type: "component",
componentName: "stdin",
title: "STDIN",
isClosable: false,
componentState: {
readOnly: false
}
}]
}, {
type: "stack",
content: [{
type: "component",
componentName: "stdout",
title: "STDOUT",
isClosable: false,
componentState: {
readOnly: true
}
}, {
type: "component",
componentName: "stderr",
title: "STDERR",
isClosable: false,
componentState: {
readOnly: true
}
},
]
}]
}]
}]
};
function encode(str) {
return btoa(unescape(encodeURIComponent(str || "")));
}
function decode(bytes) {
var escaped = escape(atob(bytes || ""));
try {
return decodeURIComponent(escaped);
} catch {
return unescape(escaped);
}
}
function localStorageSetItem(key, value) {
try {
localStorage.setItem(key, value);
} catch (ignorable) {
}
}
function localStorageGetItem(key) {
try {
return localStorage.getItem(key);
} catch (ignorable) {
return null;
}
}
function showError(title, content) {
$("#site-modal #title").html(title);
$("#site-modal .content").html(content);
$("#site-modal").modal("show");
}
function handleError(jqXHR, textStatus, errorThrown) {
showError(`${jqXHR.statusText} (${jqXHR.status})`, `<pre>${JSON.stringify(jqXHR, null, 4)}</pre>`);
}
function handleRunError(jqXHR, textStatus, errorThrown) {
handleError(jqXHR, textStatus, errorThrown);
$runBtn.removeClass("loading");
}
function handleResult(data) {
timeEnd = performance.now();
var status = data.status;
var stdout = decode(data.stdout);
var stderr = decode(data.stderr);
var compile_output = decode(data.compile_output);
var time = (data.time === null ? "-" : data.time + "s");
var memory = (data.memory === null ? "-" : data.memory + "KB");
stdoutEditor.setValue(compile_output + stdout + `\n[${status.description}, ${time}, ${memory}]`);
stderrEditor.setValue(stderr);
if (stdout !== "") {
var dot = document.getElementById("stdout-dot");
if (!dot.parentElement.classList.contains("lm_active")) {
dot.hidden = false;
}
}
if (stderr !== "") {
var dot = document.getElementById("stderr-dot");
if (!dot.parentElement.classList.contains("lm_active")) {
dot.hidden = false;
}
}
$runBtn.removeClass("loading");
}
function getIdFromURI() {
var uri = location.search.substr(1).trim();
return uri.split("&")[0];
}
function downloadSource() {
var value = parseInt($selectLanguage.val());
download(sourceEditor.getValue(), fileNames[value], "text/plain");
}
function loadSavedSource() {
snippet_id = getIdFromURI();
if (snippet_id.length == 36) {
$.ajax({
url: apiUrl + "/submissions/" + snippet_id + "?fields=source_code,language_id,stdin,stdout,stderr,compile_output,message,time,memory,status&base64_encoded=true",
type: "GET",
success: function(data, textStatus, jqXHR) {
sourceEditor.setValue(decode(data["source_code"]));
$selectLanguage.dropdown("set selected", data["language_id"]);
stdinEditor.setValue(decode(data["stdin"]));
stderrEditor.setValue(decode(data["stderr"]));
var time = (data.time === null ? "-" : data.time + "s");
var memory = (data.memory === null ? "-" : data.memory + "KB");
stdoutEditor.setValue(decode(data["compile_output"]) + decode(data["stdout"]) + `\n[${data.status.description}, ${time}, ${memory}]`);
changeEditorLanguage();
},
error: handleRunError
});
} else {
loadRandomLanguage();
}
}
function run() {
if (sourceEditor.getValue().trim() === "") {
showError("Error", "Source code can't be empty!");
return;
} else {
$runBtn.addClass("loading");
}
document.getElementById("stdout-dot").hidden = true;
document.getElementById("stderr-dot").hidden = true;
stdoutEditor.setValue("");
stderrEditor.setValue("");
var sourceValue = encode(sourceEditor.getValue());
var stdinValue = encode(stdinEditor.getValue());
var languageId = resolveLanguageId($selectLanguage.val());
if (parseInt(languageId) === 44) {
sourceValue = sourceEditor.getValue();
}
var data = {
source_code: sourceValue,
language_id: languageId,
stdin: stdinValue,
redirect_stderr_to_stdout: redirectStderrToStdout
};
var sendRequest = function(data) {
timeStart = performance.now();
$.ajax({
url: apiUrl + `/submissions?base64_encoded=true&wait=${wait}`,
type: "POST",
async: true,
contentType: "application/json",
data: JSON.stringify(data),
xhrFields: {
withCredentials: apiUrl.indexOf("/secure") != -1 ? true : false
},
success: function (data, textStatus, jqXHR) {
console.log(data.token);
if (wait == true) {
handleResult(data);
} else {
setTimeout(fetchSubmission.bind(null, data.token), check_timeout);
}
},
error: handleRunError
});
}
sendRequest(data);
}
function fetchSubmission(submission_token) {
$.ajax({
url: apiUrl + "/submissions/" + submission_token + "?base64_encoded=true",
type: "GET",
async: true,
success: function (data, textStatus, jqXHR) {
if (data.status.id <= 2) { // In Queue or Processing
setTimeout(fetchSubmission.bind(null, submission_token), check_timeout);
return;
}
handleResult(data);
},
error: handleRunError
});
}
function changeEditorLanguage() {
monaco.editor.setModelLanguage(sourceEditor.getModel(), $selectLanguage.find(":selected").attr("mode"));
currentLanguageId = parseInt($selectLanguage.val());
$(".lm_title")[0].innerText = fileNames[currentLanguageId];
apiUrl = resolveApiUrl($selectLanguage.val());
}
function insertTemplate() {
currentLanguageId = parseInt($selectLanguage.val());
sourceEditor.setValue(sources[currentLanguageId]);
changeEditorLanguage();
}
function loadRandomLanguage() {
var values = [];
for (var i = 0; i < $selectLanguage[0].options.length; ++i) {
values.push($selectLanguage[0].options[i].value);
}
// $selectLanguage.dropdown("set selected", values[Math.floor(Math.random() * $selectLanguage[0].length)]);
$selectLanguage.dropdown("set selected", values[9]);
apiUrl = resolveApiUrl($selectLanguage.val());
insertTemplate();
}
function resizeEditor(layoutInfo) {
if (editorMode != "normal") {
var statusLineHeight = $("#editor-status-line").height();
layoutInfo.height -= statusLineHeight;
layoutInfo.contentHeight -= statusLineHeight;
}
}
function disposeEditorModeObject() {
try {
editorModeObject.dispose();
editorModeObject = null;
} catch(ignorable) {
}
}
function changeEditorMode() {
disposeEditorModeObject();
if (editorMode == "vim") {
editorModeObject = MonacoVim.initVimMode(sourceEditor, $("#editor-status-line")[0]);
} else if (editorMode == "emacs") {
var statusNode = $("#editor-status-line")[0];
editorModeObject = new MonacoEmacs.EmacsExtension(sourceEditor);
editorModeObject.onDidMarkChange(function(e) {
statusNode.textContent = e ? "Mark Set!" : "Mark Unset";
});
editorModeObject.onDidChangeKey(function(str) {
statusNode.textContent = str;
});
editorModeObject.start();
}
}
function resolveLanguageId(id) {
id = parseInt(id);
return id;
}
function resolveApiUrl(id) {
id = parseInt(id);
return apiUrl;
}
function editorsUpdateFontSize(fontSize) {
sourceEditor.updateOptions({fontSize: fontSize});
stdinEditor.updateOptions({fontSize: fontSize});
stdoutEditor.updateOptions({fontSize: fontSize});
stderrEditor.updateOptions({fontSize: fontSize});
}
function getDefaultTheme() {
return localStorageGetItem('editor-theme') || 'vs-dark';
}
function editorsUpdateTheme(isInit) {
var theme = $selectTheme.val();
if (isInit) {
theme = getDefaultTheme();
$selectTheme.val(theme).change();
}
else localStorageSetItem('editor-theme', theme);
var $siteNavigation = $("#site-navigation");
if (theme == 'vs') {
$siteNavigation.removeClass('inverted');
$siteNavigation.css('background', 'white');
}
else {
$("#site-navigation").addClass('inverted');
$siteNavigation.css('background', '#1e1e1e');
}
sourceEditor.updateOptions({theme: theme});
stdinEditor.updateOptions({theme: theme});
stdoutEditor.updateOptions({theme: theme});
stderrEditor.updateOptions({theme: theme});
}
function updateScreenElements() {
var display = window.innerWidth <= 1200 ? "none" : "";
$(".wide.screen.only").each(function(index) {
$(this).css("display", display);
});
}
$(window).resize(function() {
layout.updateSize();
updateScreenElements();
});
$(document).ready(function () {
updateScreenElements();
$selectLanguage = $("#select-language");
$selectLanguage.change(function (e) {
if (!isEditorDirty) {
insertTemplate();
} else {
changeEditorLanguage();
}
});
$selectTheme = $("#select-theme");
$selectTheme.change(function(e) {
editorsUpdateTheme(false);
});
$insertTemplateBtn = $("#insert-template-btn");
$insertTemplateBtn.click(function (e) {
if (isEditorDirty && confirm("Are you sure? Your current changes will be lost.")) {
insertTemplate();
}
});
$runBtn = $("#run-btn");
$runBtn.click(function (e) {
run();
});
$(`input[name="editor-mode"][value="${editorMode}"]`).prop("checked", true);
$("input[name=\"editor-mode\"]").on("change", function(e) {
editorMode = e.target.value;
localStorageSetItem("editorMode", editorMode);
resizeEditor(sourceEditor.getLayoutInfo());
changeEditorMode();
sourceEditor.focus();
});
$("input[name=\"redirect-output\"]").prop("checked", redirectStderrToStdout)
$("input[name=\"redirect-output\"]").on("change", function(e) {
redirectStderrToStdout = e.target.checked;
localStorageSetItem("redirectStderrToStdout", redirectStderrToStdout);
});
$("body").keydown(function (e) {
var keyCode = e.keyCode || e.which;
if (keyCode == 120 || (event.ctrlKey && keyCode == 66)) { // F9 || ctrl B
e.preventDefault();
run();
} else if (event.ctrlKey && (keyCode == 107 || keyCode == 187)) { // Ctrl++
e.preventDefault();
fontSize += 1;
editorsUpdateFontSize(fontSize);
} else if (event.ctrlKey && (keyCode == 107 || keyCode == 189)) { // Ctrl+-
e.preventDefault();
fontSize -= 1;
editorsUpdateFontSize(fontSize);
}
});
$("select.dropdown").dropdown();
$(".ui.dropdown").dropdown();
$(".ui.dropdown.site-links").dropdown({action: "hide", on: "hover"});
$(".ui.checkbox").checkbox();
$(".message .close").on("click", function () {
$(this).closest(".message").transition("fade");
});
require(["vs/editor/editor.main", "monaco-vim", "monaco-emacs"], function (ignorable, MVim, MEmacs) {
layout = new GoldenLayout(layoutConfig, $("#site-content"));
MonacoVim = MVim;
MonacoEmacs = MEmacs;
layout.registerComponent("source", function (container, state) {
sourceEditor = monaco.editor.create(container.getElement()[0], {
automaticLayout: true,
theme: getDefaultTheme(),
scrollBeyondLastLine: true,
readOnly: state.readOnly,
language: "cpp",
minimap: {
enabled: false
},
matchBrackets: false,
});
changeEditorMode();
sourceEditor.getModel().onDidChangeContent(function (e) {
currentLanguageId = parseInt($selectLanguage.val());
isEditorDirty = sourceEditor.getValue() != sources[currentLanguageId];
});
sourceEditor.onDidLayoutChange(resizeEditor);
sourceEditor.onDidChangeCursorPosition(function(e) {
var line = sourceEditor.getPosition().lineNumber;
var col = sourceEditor.getPosition().column;
$('#cursor-position').html(`Line ${line}, Column ${col}`)
})
});
layout.registerComponent("stdin", function (container, state) {
stdinEditor = monaco.editor.create(container.getElement()[0], {
automaticLayout: true,
theme: getDefaultTheme(),
scrollBeyondLastLine: false,
readOnly: state.readOnly,
language: "plaintext",
minimap: {
enabled: false
},
wordWrap: "on",
});
});
layout.registerComponent("stdout", function (container, state) {
stdoutEditor = monaco.editor.create(container.getElement()[0], {
automaticLayout: true,
theme: getDefaultTheme(),
scrollBeyondLastLine: false,
readOnly: state.readOnly,
language: "plaintext",
minimap: {
enabled: false
},
wordWrap: "on",
});
container.on("tab", function(tab) {
tab.element.append("<span id=\"stdout-dot\" class=\"dot\" hidden></span>");
tab.element.on("mousedown", function(e) {
e.target.closest(".lm_tab").children[3].hidden = true;
});
});
});
layout.registerComponent("stderr", function (container, state) {
stderrEditor = monaco.editor.create(container.getElement()[0], {
automaticLayout: true,
theme: getDefaultTheme(),
scrollBeyondLastLine: false,
readOnly: state.readOnly,
language: "plaintext",
minimap: {
enabled: false
},
wordWrap: "on",
});
container.on("tab", function(tab) {
tab.element.append("<span id=\"stderr-dot\" class=\"dot\" hidden></span>");
tab.element.on("mousedown", function(e) {
e.target.closest(".lm_tab").children[3].hidden = true;
});
});
});
layout.on("initialised", function () {
$(".monaco-editor")[0].appendChild($("#editor-status-line")[0]);
if (getIdFromURI()) {
loadSavedSource();
} else {
loadRandomLanguage();
}
$("#site-navigation").css("border-bottom", "1px solid black");
sourceEditor.focus();
editorsUpdateFontSize(fontSize);
editorsUpdateTheme(true);
});
layout.init();
});
});
// Template Sources
var assemblySource = "\
section .text\n\
global _start\n\
\n\
_start:\n\
\n\
xor eax, eax\n\
lea edx, [rax+len]\n\
mov al, 1\n\
mov esi, msg\n\
mov edi, eax\n\
syscall\n\
\n\
xor edi, edi\n\
lea eax, [rdi+60]\n\
syscall\n\
\n\
section .rodata\n\
\n\
msg db 'hello, world', 0xa\n\
len equ $ - msg\n\
";
var bashSource = "echo \"hello, world\"";
var basicSource = "PRINT \"hello, world\"";
var cSource = "\
// Powered by Judge0\n\
#include <stdio.h>\n\
\n\
int main(void) {\n\
printf(\"Hello Judge0!\\n\");\n\
return 0;\n\
}\n\
";
var csharpSource = "\
public class Hello {\n\
public static void Main() {\n\
System.Console.WriteLine(\"hello, world\");\n\
}\n\
}\n\
";
var cppSource = "\
#include <iostream>\n\
\n\
int main() {\n\
std::cout << \"hello, world\" << std::endl;\n\
return 0;\n\
}\n\
";
var clojureSource = "(println \"hello, world\")\n";
var cobolSource = "\
IDENTIFICATION DIVISION.\n\
PROGRAM-ID. MAIN.\n\
PROCEDURE DIVISION.\n\
DISPLAY \"hello, world\".\n\
STOP RUN.\n\
";
var lispSource = "(write-line \"hello, world\")";
var dSource = "\
import std.stdio;\n\
\n\
void main()\n\
{\n\
writeln(\"hello, world\");\n\
}\n\
";
var elixirSource = "IO.puts \"hello, world\"";
var erlangSource = "\
main(_) ->\n\
io:fwrite(\"hello, world\\n\").\n\
";
var executableSource = "\
Judge0 IDE assumes that content of executable is Base64 encoded.\n\
\n\
This means that you should Base64 encode content of your binary,\n\
paste it here and click \"Run\".\n\
\n\
Here is an example of compiled \"hello, world\" NASM program.\n\
Content of compiled binary is Base64 encoded and used as source code.\n\
\n\
https://ide.judge0.com/?kS_f\n\
";
var fsharpSource = "printfn \"hello, world\"\n";
var fortranSource = "\
program main\n\
print *, \"hello, world\"\n\
end\n\
";
var goSource = "\
package main\n\
\n\
import \"fmt\"\n\
\n\
func main() {\n\
fmt.Println(\"hello, world\")\n\
}\n\
";
var groovySource = "println \"hello, world\"\n";
var haskellSource = "main = putStrLn \"hello, world\"";
var javaSource = "\
public class Main {\n\
public static void main(String[] args) {\n\
System.out.println(\"hello, world\");\n\
}\n\
}\n\
";
var javaScriptSource = "console.log(\"hello, world\");";
var kotlinSource = "\
fun main() {\n\
println(\"hello, world\")\n\
}\n\
";
var luaSource = "print(\"hello, world\")";
var objectiveCSource = "\
#import <Foundation/Foundation.h>\n\
\n\
int main() {\n\
@autoreleasepool {\n\
char name[10];\n\
scanf(\"%s\", name);\n\
NSString *message = [NSString stringWithFormat:@\"hello, %s\\n\", name];\n\
printf(\"%s\", message.UTF8String);\n\
}\n\
return 0;\n\
}\n\
";
var ocamlSource = "print_endline \"hello, world\"";
var octaveSource = "printf(\"hello, world\\n\");";
var pascalSource = "\
program Hello;\n\
begin\n\
writeln ('hello, world')\n\
end.\n\
";
var perlSource = "\
my $name = <STDIN>;\n\
print \"hello, $name\";\n\
";
var phpSource = "\
<?php\n\
print(\"hello, world\\n\");\n\
?>\n\
";
var plainTextSource = "hello, world\n";
var prologSource = "\
:- initialization(main).\n\
main :- write('hello, world\\n').\n\
";
var pythonSource = "print(\"hello, world\")";
var rSource = "cat(\"hello, world\\n\")";
var rubySource = "puts \"hello, world\"";
var rustSource = "\
fn main() {\n\
println!(\"hello, world\");\n\
}\n\
";
var scalaSource = "\
object Main {\n\
def main(args: Array[String]) = {\n\
val name = scala.io.StdIn.readLine()\n\
println(\"hello, \"+ name)\n\
}\n\
}\n\
";
var swiftSource = "\
import Foundation\n\
let name = readLine()\n\
print(\"hello, \\(name!)\")\n\
";
var typescriptSource = "console.log(\"hello, world\");";
var vbSource = "\
Public Module Program\n\
Public Sub Main()\n\
Console.WriteLine(\"hello, world\")\n\
End Sub\n\
End Module\n\
";
var sources = {
45: assemblySource,
46: bashSource,
47: basicSource,
48: cSource,
49: cSource,
50: cSource,
51: csharpSource,
52: cppSource,
53: cppSource,
54: cppSource,
55: lispSource,
56: dSource,
57: elixirSource,
58: erlangSource,
44: executableSource,
59: fortranSource,
60: goSource,
61: haskellSource,
62: javaSource,
63: javaScriptSource,
64: luaSource,
65: ocamlSource,
66: octaveSource,
67: pascalSource,
68: phpSource,
43: plainTextSource,
69: prologSource,
70: pythonSource,
71: pythonSource,
72: rubySource,
73: rustSource,
74: typescriptSource,
75: cSource,
76: cppSource,
77: cobolSource,
78: kotlinSource,
79: objectiveCSource,
80: rSource,
81: scalaSource,
83: swiftSource,
84: vbSource,
85: perlSource,
86: clojureSource,
87: fsharpSource,
88: groovySource,
};
var fileNames = {
45: "main.asm",
46: "script.sh",
47: "main.bas",
48: "main.c",
49: "main.c",
50: "main.c",
51: "Main.cs",
52: "main.cpp",
53: "main.cpp",
54: "main.cpp",
55: "script.lisp",
56: "main.d",
57: "script.exs",
58: "main.erl",
44: "a.out",
59: "main.f90",
60: "main.go",
61: "main.hs",
62: "Main.java",
63: "script.js",
64: "script.lua",
65: "main.ml",
66: "script.m",
67: "main.pas",
68: "script.php",
43: "text.txt",
69: "main.pro",
70: "script.py",
71: "script.py",
72: "script.rb",
73: "main.rs",
74: "script.ts",
75: "main.c",
76: "main.cpp",
77: "main.cob",
78: "Main.kt",
79: "main.m",
80: "script.r",
81: "Main.scala",
83: "Main.swift",
84: "Main.vb",
85: "script.pl",
86: "main.clj",
87: "script.fsx",
88: "script.groovy",
};