diff --git a/webapp/src/app/live-edit.js b/webapp/src/app/live-edit.js
index 99802c08..41cf355f 100644
--- a/webapp/src/app/live-edit.js
+++ b/webapp/src/app/live-edit.js
@@ -32,48 +32,46 @@ class LiveEdit {
.replace(/'/g, ''');
}
- processGccCompletion(result) {
- SysGlobalObservables.gccErrorCount(0);
- SysGlobalObservables.gccWarningCount(0);
-
- if (!result) {
- // cancelled
- SysGlobalObservables.compileStatus('Cancelled');
- return;
- }
-
- // null if cancelled
- // result = { 'exitcode':gcc_exit_code, 'stats':stats,'annotations':annotations,'gcc_ouput':gcc_output}
-
- this.runtime.sendKeys('tty0', 'clear\n');
-
- const aceAnnotations = [];
- const buildCmdErrors = [];
- result.annotations.forEach((annotation) => {
- if (annotation.isBuildCmdError) {
- buildCmdErrors.push(annotation);
+ runCode(buildCmd, execCmd) {
+ SysGlobalObservables.fileBrowser.saveActiveFile();
+ const callback = (result) => {
+ SysGlobalObservables.gccErrorCount(0);
+ SysGlobalObservables.gccWarningCount(0);
+
+ if (!result) {
+ // cancelled
+ SysGlobalObservables.compileStatus('Cancelled');
+ return;
+ }
+
+ // null if cancelled
+ // result = { 'exitcode':gcc_exit_code, 'stats':stats,'annotations':annotations,'gcc_ouput':gcc_output}
+
+ this.runtime.sendKeys('tty0', 'clear\n');
+
+ const aceAnnotations = [];
+ const buildCmdErrors = [];
+ result.annotations.forEach((annotation) => {
+ if (annotation.isBuildCmdError) {
+ buildCmdErrors.push(annotation);
+ } else {
+ aceAnnotations.push(annotation);
+ }
+ });
+
+ SysGlobalObservables.editorAnnotations(aceAnnotations);
+ SysGlobalObservables.lastGccOutput(result.gccOutput);
+ SysGlobalObservables.gccErrorCount(result.stats.error);
+ SysGlobalObservables.gccWarningCount(result.stats.warning);
+ SysGlobalObservables.gccOptsError(buildCmdErrors.map((error) => error.text).join('\n'));
+
+ if (result.exitCode === 0) {
+ SysGlobalObservables.compileStatus(result.stats.warning > 0 ? 'Warnings' : 'Success');
+ this.runtime.sendExecCmd(execCmd);
} else {
- aceAnnotations.push(annotation);
+ SysGlobalObservables.compileStatus('Failed');
}
- });
-
- SysGlobalObservables.editorAnnotations(aceAnnotations);
- SysGlobalObservables.lastGccOutput(result.gccOutput);
- SysGlobalObservables.gccErrorCount(result.stats.error);
- SysGlobalObservables.gccWarningCount(result.stats.warning);
- SysGlobalObservables.gccOptsError(buildCmdErrors.map((error) => error.text).join('\n'));
-
- if (result.exitCode === 0) {
- SysGlobalObservables.compileStatus(result.stats.warning > 0 ? 'Warnings' : 'Success');
- this.runtime.sendExecCmd(SysGlobalObservables.execCmd());
- } else {
- SysGlobalObservables.compileStatus('Failed');
}
- }
-
- runCode(buildCmd) {
- SysGlobalObservables.fileBrowser.saveActiveFile();
- const callback = this.processGccCompletion.bind(this);
SysGlobalObservables.compileStatus('Compiling');
this.runtime.startBuild(buildCmd, callback);
}
diff --git a/webapp/src/app/sys-global-observables.js b/webapp/src/app/sys-global-observables.js
index dc1b8090..28dabe62 100644
--- a/webapp/src/app/sys-global-observables.js
+++ b/webapp/src/app/sys-global-observables.js
@@ -4,10 +4,11 @@ export const vmState = ko.observable('');
export const compileStatus = ko.observable('');
export const focusTerm = ko.observable((tty) => {});
-export const runCode = ko.observable((gccOptions) => {});
+export const runCode = ko.observable((gccOptions, nextCommand) => {});
export const buildCmd = ko.observable('');
export const execCmd = ko.observable('');
+export const testCmd = ko.observable('');
export const lastGccOutput = ko.observable('');
export const gccOptsError = ko.observable('');
diff --git a/webapp/src/app/sys-runtime.js b/webapp/src/app/sys-runtime.js
index 270c3a55..95b89167 100644
--- a/webapp/src/app/sys-runtime.js
+++ b/webapp/src/app/sys-runtime.js
@@ -226,9 +226,6 @@ class SysRuntime {
if (!cmd) {
return;
}
- if (cmd[0] !== '/' && cmd[0] !== '.') {
- cmd = './' + cmd.replace(' ', '\\ ');
- }
cmd = cmd.replace('\\', '\\\\').replace('\n', '\\n');
// Don't \x03 ; it interrupts the clear command
this.sendKeys('tty0', '\n' + cmd + '\n');
diff --git a/webapp/src/components/compiler-controls/compiler-controls.html b/webapp/src/components/compiler-controls/compiler-controls.html
index b5413a3a..dedd71e8 100644
--- a/webapp/src/components/compiler-controls/compiler-controls.html
+++ b/webapp/src/components/compiler-controls/compiler-controls.html
@@ -23,5 +23,12 @@
Run It
+
diff --git a/webapp/src/components/compiler-controls/compiler-controls.js b/webapp/src/components/compiler-controls/compiler-controls.js
index 63638730..3df62c40 100644
--- a/webapp/src/components/compiler-controls/compiler-controls.js
+++ b/webapp/src/components/compiler-controls/compiler-controls.js
@@ -29,6 +29,18 @@ class CompilerControls {
$compileBtn.popover('hide');
});
+ const $testBtn = $('#test-btn');
+ $testBtn.click(() => {
+ params.testCallback();
+ $testBtn.popover('hide');
+ });
+
+ if (params.enableTest) {
+ $testBtn.show();
+ } else {
+ $testBtn.hide();
+ }
+
// Initialize Bootstrap popovers
$compileBtn.popover();
// We don't want the "gcc opts errors" popover to be dismissed when clicked
diff --git a/webapp/src/components/play-activity-page/play-activity-page.js b/webapp/src/components/play-activity-page/play-activity-page.js
index 329493a5..d01bd463 100644
--- a/webapp/src/components/play-activity-page/play-activity-page.js
+++ b/webapp/src/components/play-activity-page/play-activity-page.js
@@ -23,6 +23,7 @@ int main() {
`;
const defaultBuildCmd = 'gcc -lm -Wall -fmax-errors=10 -Wextra program.c -o program';
const defaultExecCmd = './program';
+const defaultTestCmd = 'echo "No tests!"';
class PlayActivityPage {
@@ -63,6 +64,17 @@ class PlayActivityPage {
}
this.compilerParams.execCmd(execCmd);
+ let testCmd = defaultTestCmd;
+ this.compilerParams.enableTest = true;
+ if (typeof playActivity.testCmd !== 'undefined') {
+ testCmd = playActivity.testCmd
+ } else if (typeof playActivity.testLocation !== 'undefined') {
+ testCmd = `${playActivity.testLocation}`
+ } else {
+ this.compilerParams.enableTest = false;
+ }
+ this.compilerParams.testCmd(testCmd);
+
if (playActivity.docFile) {
this.doc = {
url: 'https://cs-education.github.io/sysassets/' + playActivity.docFile,
@@ -80,6 +92,7 @@ class PlayActivityPage {
this.editorParams.initialEditorText = defaultEditorText;
this.compilerParams.buildCmd(defaultBuildCmd);
this.compilerParams.execCmd(defaultExecCmd);
+ this.compilerParams.testCmd(defaultTestCmd)
this.doc = {
text: '# Welcome\n' +
@@ -129,6 +142,7 @@ class PlayActivityPage {
this.compilerParams = {
buildCmd: SysGlobalObservables.buildCmd,
execCmd: SysGlobalObservables.execCmd,
+ testCmd: SysGlobalObservables.testCmd,
compileStatus: SysGlobalObservables.compileStatus,
lastGccOutput: SysGlobalObservables.lastGccOutput,
gccOptsError: SysGlobalObservables.gccOptsError,
@@ -155,11 +169,25 @@ class PlayActivityPage {
this.autoIncluder.addMissingHeaders(this.editorParams.editorTextGetter);
}
const buildCmd = this.compilerParams.buildCmd();
- (SysGlobalObservables.runCode())(buildCmd);
+ const execCmd = this.compilerParams.execCmd();
+
+ (SysGlobalObservables.runCode())(buildCmd, execCmd);
};
this.compilerParams.compileCallback = compile;
+ const compileAndTest = () => {
+ if (this.editorParams.autoInclude()) {
+ this.autoIncluder.addMissingHeaders(this.editorParams.editorTextGetter);
+ }
+ const buildCmd = this.compilerParams.buildCmd();
+ const testCmd = this.compilerParams.testCmd();
+
+ (SysGlobalObservables.runCode())(buildCmd, testCmd);
+ };
+
+ this.compilerParams.testCallback = compileAndTest;
+
this.editorParams.keyboardShortcuts.push([
'compileAndRunShortcut',
compileShortcut,