Skip to content
This repository was archived by the owner on Sep 30, 2020. It is now read-only.

Initial crop of feedback changes #28

Merged
merged 3 commits into from
Jun 4, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ ul.laundry-list {
padding: none;
margin: none;
width: 100%;
height: 340px;
min-height: 340px;
font-size: 13px;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
Expand Down Expand Up @@ -285,14 +285,24 @@ ul.laundry-list {
border-radius: 4px;
}

.ace-error-text, .ace-error-line, .ace-warning-text, .ace-warning-line {
position: absolute;
}

.ace-error-text {
background-color: #e9abab;
position: absolute;
}

.ace-error-line {
background-color: #F6E2E2;
position: absolute;
}

.ace-warning-text {
background-color: #FFEF00;
}

.ace-warning-line {
background-color: #FFFBCB;
}

pre { background-color: #FDFDFD; }
Expand Down
92 changes: 73 additions & 19 deletions js/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,27 @@ if (typeof String.prototype.startsWith != 'function') {

// Fetching DOM items
var activeCode = document.getElementById("active-code");
var editorDiv = document.getElementById("editor");
var staticCode = document.getElementById("static-code");
var runButton = document.getElementById("run-code");
var resultDiv = document.getElementById("result");

// Background colors for program result on success/error
var successColor = "#E2EEF6";
var errorColor = "#F6E2E2";
var warningColor = "#FFFBCB";

// Error message to return when there's a server failure
var errMsg = "The server encountered an error while running the program.";

// Stores ACE editor markers (highights) for errors
var markers = [];

// Status codes, because there are no enums in Javascript
var SUCCESS = 0;
var ERROR = 1;
var WARNING = 2;

// JS exists, display ACE editor
staticCode.style.display = "none";
activeCode.style.display = "block";
Expand All @@ -33,6 +40,21 @@ editor.getSession().setMode("ace/mode/rust");
editor.getSession().setTabSize(2);
editor.setShowPrintMargin(false);
editor.renderer.setShowGutter(false);
editor.setHighlightActiveLine(false);

// Changes the height of the editor to match its contents
function updateEditorHeight() {
// http://stackoverflow.com/questions/11584061/
var newHeight = editor.getSession().getScreenLength()
* editor.renderer.lineHeight
+ editor.renderer.scrollBar.getWidth();

editorDiv.style.height = Math.ceil(newHeight).toString() + "px";
editor.resize();
};

// Set initial size to match initial content
updateEditorHeight();

// Dispatches a XMLHttpRequest to the Rust playpen, running the program, and
// issues a callback to `callback` with the result (or null on error)
Expand All @@ -44,14 +66,21 @@ function runProgram(program, callback) {
code: program
});

<!-- console.log("Sending", data); -->
req.open('POST', "http://playtest.rust-lang.org/evaluate.json", true);
// console.log("Sending", data);
req.open('POST', "http://playtest.rust-lang.org/evaluate.json", true);
req.onload = function(e) {
if (req.readyState === 4 && req.status === 200) {
var result = JSON.parse(req.response).result;

// Need server support to get an accurate version of this.
var isSuccess = (result.indexOf("error:") === -1);
callback(isSuccess, result);
var statusCode = SUCCESS;
if (result.indexOf("error:") !== -1) {
statusCode = ERROR;
} else if (result.indexOf("warning:") !== -1) {
statusCode = WARNING;
}

callback(statusCode, result);
} else {
callback(false, null);
}
Expand All @@ -66,16 +95,18 @@ function runProgram(program, callback) {
}

// The callback to runProgram
function handleResult(success, message) {
function handleResult(statusCode, message) {
var message = message.replace(/<anon>/g, '');
var message = message.replace(/(?:\r\n|\r|\n)/g, '<br />');

// Dispatch depending on result type
if (result == null) {
resultDiv.style.backgroundColor = errorColor;
resultDiv.innerHTML = errMsg;
} else if (success) {
} else if (statusCode == SUCCESS) {
handleSuccess(message);
} else if (statusCode == WARNING) {
handleWarning(message);
} else {
handleError(message);
}
Expand All @@ -87,18 +118,28 @@ function handleSuccess(message) {
resultDiv.innerHTML = message;
}

// Called on unsuccessful program run. Detects and prints errors in program
// output and highlights relevant lines and text in the code.
// Called when program run results in warning(s)
function handleWarning(message) {
resultDiv.style.backgroundColor = warningColor;
handleProblem(message, "warning");
}

// Called when program run results in error(s)
function handleError(message) {
resultDiv.style.backgroundColor = errorColor;
handleProblem(message, "error");
}

// Getting list of ranges with errors
// Called on unsuccessful program run. Detects and prints problems (either
// warnings or errors) in program output and highlights relevant lines and text
// in the code.
function handleProblem(message, problem) {
// Getting list of ranges with problems
var lines = message.split("<br />");
var ranges = parseError(lines);

// Cleaning up the message: keeps only relevant error output
// Cleaning up the message: keeps only relevant problem output
var cleanMessage = lines.map(function(line) {
var errIndex = line.indexOf("error: ");
var errIndex = line.indexOf(problem + ": ");
if (errIndex !== -1) {
return line.slice(errIndex);
}
Expand All @@ -111,27 +152,30 @@ function handleError(message) {
resultDiv.innerHTML = cleanMessage;

// Highlighting the lines
var ranges = parseProblems(lines);
markers = ranges.map(function(range) {
return editor.getSession().addMarker(range, "ace-error-line", "fullLine", false);
return editor.getSession().addMarker(range, "ace-" + problem + "-line",
"fullLine", false);
});

// Highlighting the specific text
markers = markers.concat(ranges.map(function(range) {
return editor.getSession().addMarker(range, "ace-error-text", "text", false);
return editor.getSession().addMarker(range, "ace-" + problem + "-text",
"text", false);
}));
}

// Parses an error message returning a list of ranges (row:col, row:col) where
// erors in the code have occured.
function parseError(lines) {
// Parses a problem message returning a list of ranges (row:col, row:col) where
// problems in the code have occured.
function parseProblems(lines) {
var ranges = [];
for (var i in lines) {
var line = lines[i];
if (line.startsWith(":") && line.indexOf(": ") !== -1) {
var parts = line.split(/:\s?|\s+/, 5).slice(1, 5);
var ip = parts.map(function(p) { return parseInt(p, 10) - 1; });
<!-- console.log("line:", line, parts, ip); -->
ranges.push(new Range(ip[0], ip[1], ip[2], ip[3]));
// console.log("line:", line, parts, ip);
ranges.push(new Range(ip[0], ip[1], ip[2], ip[3]));
}
}

Expand All @@ -150,3 +194,13 @@ runButton.addEventListener("click", function(ev) {
var program = editor.getValue();
runProgram(program, handleResult);
});

// Highlight active line when focused
editor.on('focus', function() {
editor.setHighlightActiveLine(true);
});

// Don't when not
editor.on('blur', function() {
editor.setHighlightActiveLine(false);
});