summaryrefslogtreecommitdiff
path: root/js/prolog.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/prolog.js')
-rw-r--r--js/prolog.js122
1 files changed, 115 insertions, 7 deletions
diff --git a/js/prolog.js b/js/prolog.js
index 28c1b69..0a0eb48 100644
--- a/js/prolog.js
+++ b/js/prolog.js
@@ -3,19 +3,95 @@
*/
(function () {
+ // a constant
+ var firstCharacterPos = {'line': 0, 'ch': 0};
+
+ var makePrologTerminalHandler = function (jqConsole, editor, problem_group, problem) {
+ var promptMode = true, // default: query composition; alternative: query result browsing
+ tcs = function terminalCommandSuccess (data) {
+ var t, lines, i;
+ terminal.resume();
+ if (data.code === 0) {
+ t = data.terminal;
+ lines = t.messages;
+ for (i = 0; i < lines.length; i++) {
+ terminal.echo(lines[i]);
+ }
+ promptMode = !t.have_more;
+ }
+ else {
+ terminal.error(data.message);
+ promptMode = true;
+ }
+ },
+ tcf = function terminalCommandFailed (error) {
+ terminal.resume();
+ terminal.exception(error);
+ promptMode = true;
+ },
+ terminal = jqConsole.terminal(function (command, terminal) {
+ if (promptMode) {
+ terminal.pause();
+ codeq.comms.sendQuery({
+ 'step': 'run',
+ 'program': editor.getDoc().getValue(),
+ 'query': command,
+ 'language': 'prolog',
+ 'problem_group': problem_group,
+ 'problem': problem
+ }).then(tcs, tcf).done();
+ }
+ else {
+ // not in prompt mode -- we should never land here, but handle it anyway
+ codeq.comms.sendQuery({
+ 'step': 'end'
+ }).then(tcs, tcf).done();
+ }
+ }, {
+ 'history': true,
+ 'prompt': '?- ',
+ 'greetings': 'CodeQ prolog terminal proxy',
+ 'exit': false,
+ 'clear': false,
+ 'keypress': function (event, terminal) {
+ if (promptMode) return true;
+ setTimeout(function () {
+ terminal.echo(''); // send newline after semicolon or full-stop
+ terminal.pause();
+ }, 0);
+ if ((event.which == 32) || (event.which == 59)) {
+ // space or semicolon -> show next answer
+ event.which = 59; // semicolon
+ codeq.comms.sendQuery({
+ 'step': 'next'
+ }).then(tcs, tcf).done();
+ }
+ else {
+ // everything else: stop searching for answers
+ event.which = 46; // full stop
+ codeq.comms.sendQuery({
+ 'step': 'end'
+ }).then(tcs, tcf).done();
+ }
+ }
+ });
+
+ return {};
+ };
+
/**
* Creates a new handler for the given Prolog assignment definition.
*
* @param {PrologTaskDef} info
* @returns {{destroy: Function, processServerHints: Function}}
*/
- codeq.createPrologHandler = function (info) {
+ codeq.createPrologHandler = function (info, problem_group, problem) {
var jqDescription = $('#description'),
jqEditor = $('#code_editor'),
jqConsole = $('#console'),
jqHints = $('#info'),
editor = CodeMirror(jqEditor[0], { cursorHeight: 0.85, lineNumbers: true, matchBrackets: true }),
- controller = jqConsole.console({
+/* controller = jqConsole.console({
promptLabel: '?- ',
commandValidate: function (line) {
return !!line;
@@ -27,7 +103,9 @@
animateScroll: false,
promptHistory: false,
welcomeMessage: 'Prolog REPL.'
- }), /** Object.<string, HintDefinition> */
+ }),*/
+ terminal = makePrologTerminalHandler(jqConsole, editor, problem_group, problem),
+ /** Object.<string, HintDefinition> */
hintDefs = info.hint,
hintCounter = 0, // for generating unique class-names
hintCleaners = [],
@@ -112,7 +190,7 @@
};
if ((editor.listSelections().length > 1) || editor.somethingSelected()) {
- // showHint() doesn't work if a selection is active
+ // showHint() doesn't work if a selection is activeparts
}
editor.showHint({
@@ -131,11 +209,32 @@
hintCleaners.push(close);
}
+ },
+ lastActivityMillis = Date.now(),
+ deltaActivityMillis = function deltaActivityMillisFunc () {
+ var now = Date.now(),
+ dt = Math.max(0, Math.min(30000, now - lastActivityMillis)); // 0 sec <= dt <= 30 sec
+ lastActivityMillis = now;
+ return dt;
};
editor.setValue('sister(X, Y) :-\n female(X),\n parent(Z, X),\n parent(Z, Y),\n X \\== Y.'); // demo
jqDescription.html(info.description);
+ editor.on('change', function (instance, changeObj) {
+ var doc = editor.getDoc(),
+ pos = codeq.codePointCount(doc.getRange(firstCharacterPos, changeObj.from)),
+ dt = deltaActivityMillis();
+
+ if (changeObj.removed) {
+// codeq.comms.sendActivity({'typ': 'rm', 'dt': dt, 'off': pos, 'len': codeq.codePointCount(changeObj.removed)});
+ }
+
+ if (changeObj.text) {
+// codeq.comms.sendActivity({'typ': 'ins', 'dt': dt, 'off': pos, 'txt': changeObj.text});
+ }
+ });
+
var handler = {
destroy: function () {
jqDescription.empty();
@@ -194,9 +293,18 @@
// $(jqButtons.get(1)).on('click', function () { handler.processServerHints([{id:'popup_unknown', start: 20, end: 26}]); });
// $(jqButtons.get(2)).on('click', function () { handler.processServerHints([{id:'drop_down', start: 20, end: 26, choices:['ena', 'dva', 'tri']}]); });
- $(jqButtons.get(0)).on('click', function () { handler.processServerHints([{id:'list_empty'}]); });
- $(jqButtons.get(1)).on('click', function () { handler.processServerHints([{id:'popup_unknown', start: 20, end: 26}]); });
- $(jqButtons.get(2)).on('click', function () { handler.processServerHints([{id:'drop_down', start: 20, end: 26, choices:['ena', 'dva', 'tri']}]); });
+ $('#btn_code_run').on('click', function () {
+ var doc = editor.getDoc(),
+ dt = deltaActivityMillis();
+// codeq.comms.sendActivity({'typ': 'slv', 'dt': dt, 'qry': });
+ handler.processServerHints([{id:'list_empty'}]);
+ });
+ $('#btn_code_break').on('click', function () {
+ handler.processServerHints([{id:'popup_unknown', start: 20, end: 26}]);
+ });
+ $('#btn_code_hint').on('click', function () {
+ handler.processServerHints([{id:'drop_down', start: 20, end: 26, choices:['ena', 'dva', 'tri']}]);
+ });
return handler;
};