From 54c7fd0f65330e773460f25ca91747fad4595daf Mon Sep 17 00:00:00 2001 From: Christophe Gragnic Date: Sat, 5 Nov 2016 13:12:08 +0100 Subject: [PATCH 1/3] tentative --- web/ide_injections.js | 35 +++++++++++++++++++++++++++++++++++ web/style.css | 15 ++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/web/ide_injections.js b/web/ide_injections.js index a69bc96..b37387d 100644 --- a/web/ide_injections.js +++ b/web/ide_injections.js @@ -172,6 +172,36 @@ function preparation_exception(e) { } function attachKeyWatcher(elt, f, config_64) { + // autocompletion + elt.keyup(function (e) { + var kc = e.keyCode; + // keys we want to ignore: + // ALTGR 17 18, | 220, autres: 16 + if (kc == 16 || kc == 17 || kc == 18 || kc == 220) return; + // keys at which we want to react: + // DEL 8, SUPPR 46, SHIFT 16 + // SPACE 32 + // é->0 + // 0->9 48->57 + // A->Z 65->90 + // = 161 + // _ 173 + // < 188> 190 . 190 + // / 191 + if (kc == 8 || kc == 46 || kc == 16 || + kc == 32 || + kc == 0 || + (kc>= 48 && kc <= 57) || (kc>= 65 && kc <= 90) || + kc == 161 || kc == 173 || kc == 188 || kc == 190 || kc == 191 + ) { + console.log("cplt "); + } else { + console.log(kc); + } + var src = elt[0].value + elt[0].value = src; + }); + // run source, complete abbreviation or build blocks elt.keydown(function (e) { if (!e.ctrlKey) return; if (e.keyCode == 10 || e.keyCode == 13) { @@ -383,11 +413,16 @@ function inject_microalg_editor_in(elt_id, config) { '' + + '
' + + '' + + ' sugg.' + + '' + ' ' + + '
' + '' + diff --git a/web/style.css b/web/style.css index 4ca410b..8b95aad 100644 --- a/web/style.css +++ b/web/style.css @@ -110,12 +110,21 @@ body.microalg { width: 100%; } .malg-ok-editor { - width: 75%; + width: 73%; } -.malg-output-type { +.malg-tools { float: right; margin: 2px; - width: 20%; + width: 25%; + text-align: right; +} +.malg-suggestions { + margin-right: 1em; + padding: 2px; + border: solid 1px #aaa; +} +.malg-output-type { + text-align: center; } .malg-error { color: red; From 419e99d9a49eeef4b3d6995a8bafbf3ce4adca66 Mon Sep 17 00:00:00 2001 From: Christophe Gragnic Date: Sun, 6 Nov 2016 08:48:15 +0100 Subject: [PATCH 2/3] =?UTF-8?q?autres=20touches=20=C3=A0=20g=C3=A9rer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/ide_injections.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/web/ide_injections.js b/web/ide_injections.js index b37387d..844fba9 100644 --- a/web/ide_injections.js +++ b/web/ide_injections.js @@ -176,10 +176,13 @@ function attachKeyWatcher(elt, f, config_64) { elt.keyup(function (e) { var kc = e.keyCode; // keys we want to ignore: + // <^>v 37->40 // ALTGR 17 18, | 220, autres: 16 - if (kc == 16 || kc == 17 || kc == 18 || kc == 220) return; + if (kc == 16 || kc == 17 || kc == 18 || + (kc>= 37 && kc <= 40) || kc == 220 + ) return; // keys at which we want to react: - // DEL 8, SUPPR 46, SHIFT 16 + // DEL 8, ENTER 13, SUPPR 46, SHIFT 16 // SPACE 32 // é->0 // 0->9 48->57 @@ -188,7 +191,7 @@ function attachKeyWatcher(elt, f, config_64) { // _ 173 // < 188> 190 . 190 // / 191 - if (kc == 8 || kc == 46 || kc == 16 || + if (kc == 8 || kc == 13 || kc == 46 || kc == 16 || kc == 32 || kc == 0 || (kc>= 48 && kc <= 57) || (kc>= 65 && kc <= 90) || From feb05b5fe5576e8570aca20a9b7b5c4d7ee374fd Mon Sep 17 00:00:00 2001 From: Christophe Gragnic Date: Sun, 6 Nov 2016 20:44:14 +0100 Subject: [PATCH 3/3] Incorporation de suggestions.js --- ide.html | 1 + web/ide_injections.js | 6 +- web/suggestions.js | 243 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 web/suggestions.js diff --git a/ide.html b/ide.html index 28c8242..b1a8927 100644 --- a/ide.html +++ b/ide.html @@ -11,6 +11,7 @@ + diff --git a/web/ide_injections.js b/web/ide_injections.js index 844fba9..04e38c6 100644 --- a/web/ide_injections.js +++ b/web/ide_injections.js @@ -197,12 +197,12 @@ function attachKeyWatcher(elt, f, config_64) { (kc>= 48 && kc <= 57) || (kc>= 65 && kc <= 90) || kc == 161 || kc == 173 || kc == 188 || kc == 190 || kc == 191 ) { - console.log("cplt "); + var src = elt[0].value + console.log(propo_type(src)); + // elt[0].value = src; } else { console.log(kc); } - var src = elt[0].value - elt[0].value = src; }); // run source, complete abbreviation or build blocks elt.keydown(function (e) { diff --git a/web/suggestions.js b/web/suggestions.js new file mode 100644 index 0000000..17267ba --- /dev/null +++ b/web/suggestions.js @@ -0,0 +1,243 @@ +// apparence différent de Sugg pour ESPACE et +// pour commandes sans arg car "RAZ)" +// certaines cmds forcément suivies de SPACE +// pas plus de 10 Sugg?, au moins 2 chars? +// ! commandes à accents (détection slt, pas Sugg) + +function valid(char) +{ + return char.match(/\w/); +} +var cmdInfo = { + "Afficher": { + "maxArgs": 1, + "sigs": [["?"]]} +}; +function maxArgs(cmd) { + try { + return cmdInfo[cmd]['maxArgs']; + } catch (e) { + return 666; + } +} + +/* Returns type, prefix + +Types can be +? for no suggestion +val for any value +txt for text +nl for the need of a new line +sp for the need of a space +( for the need of a paren +) for the need of a paren +cmd for any command +any intermediate keyword +*/ +function propo_type(src) +{ + var toReturn = ["?", ""]; + // Split on parens or whitespace + // and keep separators + var tokensTmp = src.split(/(\s|\(|\))/) + .filter(function (str) { return str.trim(); }) + .filter(Boolean); + // Merge text containing spaces -> "texte" + var tokens = []; + var inString = false; + for (var i = 0; i < tokensTmp.length; i++) + { + if (!inString) { + if (tokensTmp[i].slice(0, 1) == '"' && + tokensTmp[i].slice(-1) != '"') { + inString = true; + } else { + tokens.push(tokensTmp[i]); + } + } else { + if (tokensTmp[i].slice(0, 1) != '"' && + tokensTmp[i].slice(-1) == '"') { + inString = false; + tokens.push('"texte"'); + } + } + } + // Trivial cases + if (tokens.length == 0) + return ["(", ""]; + if (inString) + return ["?", ""]; + // Currently in a word? + var lastChar = src.slice(-1); + if (valid(lastChar)) + { + // Set the prefix + toReturn[1] = tokens.slice(-1); + // Delete the prefix from the tokens + tokens = tokens.slice(0, -1); + } + var lastToken = tokens.slice(-1); + // Brand new instruction? + if (lastToken == "(") + { + // TODO: use code below to detect + // if we are in a sub command for + // refining the command to return + toReturn[0] = "cmd"; + return toReturn; + } + // We need the command of the instruction + // Find the last opening solo paren + var cursor = tokens.length - 1; + var openParens = 0; + var openParensOld = 0; + var tokensAfterLastOpen = 0; + while (cursor>= 0) + { + var token = tokens[cursor]; + if (token == "(") openParens++; + if (token == ")") openParens--; + if (openParens == 0 && + (token == "(" || token != ")")) + tokensAfterLastOpen++; + if (openParens == 1) break; + cursor--; + } + // We already tested if "(" was the last token, + // so we can safely add 1. + var cmd = tokens[cursor+1]; + if (lastChar == ")") + { + if (openParens == 0) + return ["nl", ""]; + else if (maxArgs(cmd) == 1) + return [")", ""]; + else return ["sp", ""]; + } + else if (lastChar == " ") + { + if (openParens == 1 && + maxArgs(cmd) + 1 == tokensAfterLastOpen) + return [")", ""]; + else if (cmd == '!!!') + return ["txt", ""]; + // TODO: gérer Si avec ses sigs + else if (cmd == 'Si' && tokensAfterLastOpen == 1) + toReturn[0] = "bool"; + else if (cmd == 'Si' && tokensAfterLastOpen == 2) + toReturn[0] = "alors"; + else if (cmd == 'Si' && tokensAfterLastOpen>= 4) + toReturn[0] = "sinon"; + else + toReturn[0] = "val"; + } + else if (lastChar == '"') + { + if (lastToken.length != 1 && + lastToken.slice(0, 1) == '"') + return [" ", ""]; // todo check nb args + } + // TODO: gérer Si avec ses sigs + // TODO: gérer aussi les accents + // Affecter_à + // Concaténer + // Déclarer + // Définir + // Répéter + else if (cmd == "Si") + { + if (tokens.indexOf("Alors", cursor) == -1) { + toReturn[0] = "alors"; + } else if (lastToken != "Alors" && tokens.indexOf("Sinon", cursor) == -1) { + toReturn[0] = "sinon"; + } + } + return toReturn; +} + +var cmds = "1000Cosinus 1000Sinus AV BC LC TD TG Affecter_a Afficher Aide Ajouter_a Cercle Concatener Contour Declarer Definir Demander Demander_un_nombre Ellipse Entier@ Epaisseur Et Exemples_de Faire Geler Initialiser@ Liste Longueur Millisecondes Nieme Nieme@ Nombre Non Ou Queue RAZ Rectangle Remplissage Repere Repeter Retirer_de Retourner Segment Si Tant_que Tester Tete Texte Triangle Type Vide? Affecter_à Concaténer Déclarer Définir Répéter".split(' '); +var vals = '( " Vrai Faux valeur_utilisateur credit_iterations sequence_tirages@ Rien'.split(' '); +var bools = '( Vrai Faux'.split(' '); + +/* predicate generator */ +function beginsWith(prefix) +{ + return function(str) { + var beginning = str.slice(0, prefix.toString().length); + return beginning == prefix; + } +} + +function matches(prefix, list) +{ + return list.filter(beginsWith(prefix)); +} + +/* Returns a completion (display and actual text) + +*/ +function suggestion(propo_type) { + var type = propo_type[0]; + var prefix = propo_type[1]; + if (type == 'cmd') + return matches(prefix, cmds); + if (type == 'val') + return matches(prefix, vals); + if (type == 'bool') + return matches(prefix, bools); + if (type == ' ') + return ["Espace"]; + if (type == 'alors') + return ["Alors"]; // 'Sinon' factoriser! + return []; +} + +// tests + +var src_propo_pairs = [ + ["", "("], + [" ", "("], + ["(bla)", "nl"], + ["(bla (", "cmd"], + ["(bla ( ", "cmd"], + ["(Demander) (Affi", "cmd"], + ["(Afficher ", "val"], + ["(Afficher tavu", "?"], + ["(Afficher tavu ", ")"], + ['(Afficher "tavu" ', ")"], + ["(Afficher (+ 1 1)", ")"], + ['(Afficher "ta vu ', "?"], + ["(Afficher tavu)", "nl"], + ["(Si ", "bool"], + ["(Si Vrai ", "alors"], + ["(Si Vrai Al", "alors"], + ["(Si (Et Vrai Faux)", "sp"], + ["(Si (Et Vrai Faux) ", "alors"], + ["(Si Vrai Alors Rien) (Si Vrai ", "alors"], + ["(Si (Et Vrai Faux) Alors ", "val"], + ["(Si (Et Vrai Faux) Alors (Afficher 1) ", "sinon"], + ["(Si (Et (Ou Vrai) Faux) ", "alors"], + ["ok"] +]; + +if (typeof console !== "undefined") { + print = console.log; +} + +function callback(elt, i) +{ + var src = elt[0]; + if (src === "ok") + { + print("ok"); + return; + } + var target_propo = elt[1]; + var attempted_propo = propo_type(src)[0]; + if (target_propo != attempted_propo) + { + print (src + ': ' + attempted_propo + ' != ' + target_propo); + } +} + +src_propo_pairs.forEach(callback); \ No newline at end of file

AltStyle によって変換されたページ (->オリジナル) /