Skip to content

Commit

Permalink
Merge pull request #454 from cs136/master
Browse files Browse the repository at this point in the history
Merge into stable.
  • Loading branch information
e45lee committed Jan 4, 2016
2 parents 1541409 + 29739ae commit 467d94f
Show file tree
Hide file tree
Showing 16 changed files with 169 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ addons:
- g++-4.8
- ca-certificates
env:
- RACKET_DIR=$HOME/racket RACKET_VERSION=6.1.1 NODE_PATH=/usr/local/lib/node_modules
- RACKET_DIR=$HOME/racket RACKET_VERSION=6.3 NODE_PATH=/usr/local/lib/node_modules
before_install:
# Get Racket
- git clone https://github.com/greghendershott/travis-racket.git >/dev/null
Expand Down
11 changes: 9 additions & 2 deletions src/collects/seashell-cli.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,24 @@
(define RUN-TIMEOUT (make-parameter #f))
(define-values (project-dir main-file test-name out-file err-file)
(command-line
#:usage-help "Seashell command-line runner. Return codes:\n 10 means failed compilation\n 20 means the program crashed at runtime\n 30 means the program failed its test\n 40 means the program passed its test"
#:usage-help "Seashell command-line tester. Return codes:\n 10 means failed compilation.\n 20 means the program crashed at runtime.\n 30 means the program failed its test.\n 40 means the program passed its test."
#:once-each
[("-t" "--timeout") timeout
"Override the default seashell timeout (seconds)"
"Override the default seashell timeout (seconds)."
(RUN-TIMEOUT (string->number timeout))]
#:args (project-dir main-file test-name out-file err-file)
(values project-dir main-file test-name out-file err-file)))

(when (RUN-TIMEOUT)
(config-set! 'program-run-timeout (RUN-TIMEOUT)))

(define temp-dir-path (make-temporary-file "seashell-runtime-~a" 'directory))
(define default-exit-handler (exit-handler))
(exit-handler (lambda (exit-code)
(delete-directory/files temp-dir-path #:must-exist? #f)
(default-exit-handler exit-code)))
(config-set! 'runtime-files-path temp-dir-path)

(define/contract (write-outputs stdout stderr)
(-> (or/c bytes? #f) (or/c bytes? #f) void?)
(when stdout
Expand Down
4 changes: 4 additions & 0 deletions src/collects/seashell-config.rkt.in
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@
"-gdwarf-4" "-O0" "-mdisable-fp-elim" "-dwarf-column-info"
;; Need this to detect global buffer overflow
"-fno-common"
;; Standard compilation mode
"-std=c99"
; Add standard static analyzer options (clang/lib/Driver/Tools.cpp:2954)
;; "-analyzer-store=region"
;; "-analyzer-opt-analyze-nested-blocks"
Expand All @@ -185,6 +187,8 @@
(cons 'host '("localhost"))
;; Location of per-user configuration directory.
(cons 'seashell (build-path (find-system-path 'home-dir) ".seashell"))
;; Location of the runtime-files directory.
(cons 'runtime-files-path (build-path (find-system-path 'home-dir) ".seashell" "runtime-files"))
;; Name of credentials file.
(cons 'seashell-creds-name (format "seashell~a-creds" @SEASHELL_API_VERSION@))
;; Name of credentials cookie
Expand Down
2 changes: 1 addition & 1 deletion src/collects/seashell/backend/project.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
;; Gets the path where runtime files are stored.
(define/contract (runtime-files-path)
(-> path?)
(build-path (read-config 'seashell) "runtime-files"))
(build-path (read-config 'runtime-files-path)))

;; (init-projects)
;; Creates the directories for projects
Expand Down
4 changes: 2 additions & 2 deletions src/collects/seashell/websocket/server.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(require racket/contract
racket/unit
racket/tcp
net/tcp-sig
net/url
(prefix-in raw: net/tcp-unit)
Expand All @@ -28,7 +29,6 @@
web-server/private/connection-manager
web-server/private/timer
racket/async-channel
unstable/contract
seashell/websocket/connection
seashell/websocket/handshake)

Expand Down Expand Up @@ -119,7 +119,7 @@
#:tcp@
(unit/c (import) (export tcp^))
#:port
tcp-listen-port?
listen-port-number?
#:listen-ip
(or/c string? false/c)
#:max-waiting
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/css/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ body {
font-size: 1.2em;
padding-top: 0;
padding-left: 0;
padding-right: 5px;
padding-right: 1em;
text-decoration: none;
font-variant: small-caps;
}
Expand Down
29 changes: 23 additions & 6 deletions src/frontend/frontend/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,27 @@ angular.module('frontend-app')
}
};
}])
.directive('focusOn', ['$timeout', function($timeout) {
return function(scope, elem, attr) {
scope.$on(attr.focusOn, function(e) {
$timeout(function () {elem[0].focus();});
.directive('focusOn', ['$timeout', function ($timeout) {
return function (scope, elem, attr) {
scope.$on(attr.focusOn, function (e) {
$timeout(function () {
elem[0].focus();
});
};
}]);
});
};
}])
.directive('focusMe', function ($timeout, $parse) {
return {
link: function (scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function (value) {
if (value === true) {
$timeout(function () {
element[0].focus();
});
}
});
}
};
});

21 changes: 13 additions & 8 deletions src/frontend/frontend/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ angular.module('frontend-app')
self.project = openProject;
self.question = openQuestion;
self.folder = openFolder;
self.file = openFile;
self.file = openFile;
self.console = Console;
self.settings = settings;
self.undoHistory = undoHistory;
Expand All @@ -44,6 +44,8 @@ angular.module('frontend-app')
self.isBinaryFile = false;
self.ready = false;
self.ext = self.file.split(".")[1];
self.runnerFile = false; // true if a runner file is present in the project
self.isFileToRun = false; // true if the current file is the runner file
self.editor = null;
self.timeout = null;
self.loaded = false;
Expand Down Expand Up @@ -289,7 +291,7 @@ angular.module('frontend-app')
self.runFile();
}
}, {
combo: 'ctrl+u',
combo: 'ctrl+e',
description: "Starts Tests",
allowIn: ['INPUT', 'SELECT', 'TEXTAREA'],
callback: function (evt) {
Expand Down Expand Up @@ -425,14 +427,15 @@ angular.module('frontend-app')
if(!self.console.PIDs) {
return $q.when();
}
return $q.all(_.map(self.console.PIDs, function(id) {
var p = $q.all(_.map(self.console.PIDs, function(id) {
return self.project.kill(id);
}))
.catch(function (error) {
errors.report(error, "Could not stop program!");
self.console.PIDs = null;
self.console.running = false;
});
self.console.running = false;
self.console.PIDs = null;
return p;
};

self.indentAll = function() {
Expand Down Expand Up @@ -483,11 +486,12 @@ angular.module('frontend-app')
.then(function () {
$scope.$emit('setFileToRun', []);
self.runnerFile = true;
self.isFileToRun = true;
})
.catch(function (error) {
errors.report(error, "Could not set runner file!");
});

// emit an event to the parent scope for
// since EditorController is in the child scope of EditorFileController

Expand Down Expand Up @@ -525,11 +529,12 @@ angular.module('frontend-app')
function has_ext(ext, fname){
return fname.split(".").pop() === ext;
}

self.refreshRunner = function () {
self.project.getFileToRun(self.question)
.then(function (result) {
.then(function (result) {
self.runnerFile = (result !== "");
self.isFileToRun = (result === self.file);
});
};
self.refreshRunner();
Expand Down
46 changes: 46 additions & 0 deletions src/frontend/frontend/modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,52 @@ angular.module('frontend-app')
}).result;
};
}])

.factory('NewTestModal', ['$modal', 'error-service',
function ($modal, errors) {
return function(project, question, notify) {
notify = notify || function () {};
return $modal.open({
templateUrl: "frontend/templates/new-test-template.html",
controller: ['$scope', '$state', 'error-service', '$q',
function($scope, $state, errors, $q) {
$scope.new_file_name = "";
$scope.question = question;
$scope.inputError = false;
$scope.newTest = function () {
// three cases:
// a .in or .expect file, which we create normally
// a file without an extension, for which we create a pair
// an invalid extension
var filename = $scope.new_file_name;
var extension = filename.split('.').pop();
var results = [];
if (extension === 'in' || extension === 'expect') {
results.push(project.createFile("tests", question, filename));
} else if (filename.split('.').length < 2) {
// no extension
results.push(project.createFile("tests", question, filename + ".in"));
results.push(project.createFile("tests", question, filename + ".expect"));
} else {
$scope.inputError = "Invalid test file name.";
return false;
}
_.each(results, function (result) {
result.then(function () {
notify(false, true, project, question, $scope.new_file_folder, filename);
}).catch(function (error) {
notify(false, false, project, question, $scope_new_file_folder, filename);
});
});
$scope.$close();

};
}]
}).results;
};
}])


// Directive for New Question Modal Service
.factory('NewQuestionModal', ['$modal', 'error-service',
function ($modal, errors){
Expand Down
12 changes: 10 additions & 2 deletions src/frontend/frontend/question.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
angular.module('frontend-app')
// Editor Controller
.controller("EditorController", ['$state', 'openQuestion', '$scope', 'error-service',
'openProject', 'NewFileModal', 'SubmitMarmosetModal', '$interval', 'marmoset',
'openProject', 'NewFileModal', 'NewTestModal', 'SubmitMarmosetModal', '$interval', 'marmoset',
'NewQuestionModal', 'MarmosetResultsModal', 'console-service',
function ($state, openQuestion, $scope, errors,
openProject, newFileModal, submitMarmosetModal,
openProject, newFileModal, newTestModal, submitMarmosetModal,
$interval, marmoset, newQuestionModal,
marmosetResultsModal, Console) {
var self = this;
Expand Down Expand Up @@ -153,6 +153,14 @@ angular.module('frontend-app')
});
};

/** Adds a pair of .in and .expect files to the project
*/
self.add_test = function () {
newTestModal(self.project, self.question, function () {
self.refresh();
});
};

/** Dispatches a function to run when the
* current file is saved.
*
Expand Down
1 change: 1 addition & 0 deletions src/frontend/frontend/templates/new-file-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ <h4 class="modal-title" id="new-file-label">New file...</h4>
name="new_file_name"
class="form-control"
placeholder="(file name)"
focus-me="true"
style="outline: none; width: 200px; padding-left: 5px">
<span class="help-block" ng-show="inputError">{{inputError}}</span>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/frontend/templates/new-project-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h4 class="modal-title" id="new-project-label">
ng-class="{'has-error': newProjectForm.new_project_name.$invalid}">
<label class="control-label col-sm-4" for="new_project_name">Project Name:</label>
<div class="col-sm-6">
<input type="text" id="new_project_name" ng-model="new_project_name" required name="new_project_name" class="form-control">
<input type="text" id="new_project_name" ng-model="new_project_name" required name="new_project_name" focus-me="true" class="form-control">
<span class="help-block" ng-show="newProjectForm.new_project_name.$invalid">Required</span>
</div>
</div>
Expand Down
32 changes: 32 additions & 0 deletions src/frontend/frontend/templates/new-test-template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="modal-header">
<button type="button" class="close" ng-click="$dismiss()" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="new-file-label">New test...</h4>
</div>
<form name="newTestForm" novalidate ng-submit="newTest()">
<div class="modal-body" style="font-size: 16px; padding-bottom: 0">
<div ng-class="{'has-error': inputError}" class="form-group">
<div class="row">
<div class="col-xs-4 text-right" style="padding-right: 10px">
</div>
<div class="col-xs-8" style="padding-left: 0">
<label for="new_file_name">
Test name:
</label>
<input type="text"
ng-model="new_file_name"
name="new_file_name"
class="form-control"
placeholder="(file name)"
focus-me="true"
style="outline: none; width: 200px; padding-left: 5px">
<span class="text-muted">Enter a name without an extension to create a test pair</span>
<span class="text-muted">Eg. "test" will create test.in and test.expect</span>
<span class="help-block" ng-show="inputError">{{inputError}}</span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$dismiss()">Cancel</button>
<input type="submit" class="btn btn-primary" value="OK"></input>
</div>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,22 @@
<span style="position: relative; bottom: 2px; left: 2px"> code</span>
<div id="editor-controls"
style="position: absolute; right: 13px; top: 0px">
<button id="toolbar-run-tests" ng-click="editFileView.testFile()" class="btn btn-link"
ng-disabled="!(editFileView.runnerFile)"
style="padding-left: 0; padding-right: 0; margin-right: 15px; padding-top: 2px" tooltip-placement="left" tooltip="control+U"
ng-show="editFileView.console.PIDs === null">
<span style="font-size: 18px">test</span>
</button>
<button id="toolbar-run" ng-click="editFileView.runFile()" ng-show="editFileView.console.PIDs === null" class="btn btn-link"
ng-disabled="!(editFileView.runnerFile)"
style="padding-left: 0; padding-right: 0; padding-top: 2px" tooltip-placement="left" tooltip="control+R">
style="padding-left: 0; padding-right: 0; padding-top: 2px" tooltip-placement="left" tooltip="Control+R">
<span style="font-size: 18px">run</span>
<span class="glyphicon glyphicon-play-circle"></span>
</button>
<button id="toolbar-kill" ng-click="editFileView.killProgram()" ng-show="editFileView.console.PIDs !== null" class="btn btn-link"
style="padding-left: 0; padding-right: 0; padding-top: 2px" tooltip-placement="left" tooltip="control+K">
style="padding-left: 0; padding-right: 0; padding-top: 2px" tooltip-placement="left" tooltip="Control+K">
<span style="font-size: 18px">stop</span>
</button>
<button id="toolbar-run-tests" ng-click="editFileView.testFile()" class="btn btn-link"
ng-disabled="!(editFileView.runnerFile)"
style="padding-left: 0; padding-right: 0; margin-left: 15px; padding-top: 2px" tooltip-placement="left" tooltip="control+U"
ng-show="editFileView.console.PIDs === null">
<span style="font-size: 18px">test</span>
</button>
</div>
</div>

Expand All @@ -47,12 +48,11 @@
<button id="toolbar-set-runner"
ng-click="editFileView.setFileToRun()"
class="btn btn-link"
ng-disabled="editFileView.folder !== 'question'">
<span class="glyphicon glyphicon-arrow-right runner-icon"></span>
set as runner
ng-disabled="editFileView.folder !== 'question' || editFileView.isFileToRun">
set as <span class="glyphicon glyphicon-play-circle"></span> file
</button>
<div ng-show="editFileView.editor.hasFocus()"
style="padding-top: 7px; float: right;
style="padding-top: 7px; float: right;
font-size: 14px; font-variant: small-caps; color: #999">
<span>ln {{editFileView.line}}</span>
<span ng-class="{'col-too-long': editFileView.col > 80}">col {{editFileView.col}}</span>
Expand Down Expand Up @@ -101,7 +101,7 @@ <h3 class="text-center text-muted">
<div class="console-controls"
style="position: absolute; top: 5px; right: 0"
tooltip-placement="left"
tooltip="control+D">
tooltip="Control+D">
<button id="send-eof" ng-click="editFileView.sendEOF()" ng-disabled="!editFileView.console.running"
class="btn btn-link console-control">eof</button>
</div>
Expand Down
Loading

0 comments on commit 467d94f

Please sign in to comment.