diff options
Diffstat (limited to 'js/prolog.js')
-rw-r--r-- | js/prolog.js | 122 |
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; }; |