forked from GitHub/gf-core
Syntax editor: start with initial grammar, startcat, to: languages
This commit is contained in:
@@ -11,8 +11,30 @@ An improved version of the [old syntax editor][1].
|
|||||||
|
|
||||||
- Tested with latest Chrome and Firefox (only).
|
- Tested with latest Chrome and Firefox (only).
|
||||||
|
|
||||||
|
## Available startup options
|
||||||
|
|
||||||
|
var editor_options = {
|
||||||
|
target: "editor",
|
||||||
|
initial: {
|
||||||
|
grammar: "http://localhost:41296/grammars/Foods.pgf",
|
||||||
|
startcat: "Kind",
|
||||||
|
languages: ["Eng","Swe","Mlt"],
|
||||||
|
ast: null,
|
||||||
|
node_id: null
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
grammar_menu: true,
|
||||||
|
startcat_menu: true,
|
||||||
|
to_menu: true,
|
||||||
|
random_button: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
- Link to jump into minibar
|
||||||
|
- Start with initial grammar, startcat, ast
|
||||||
|
- Compatibility with grammars with dependent category types
|
||||||
- Clicking on tokens to select tree node
|
- Clicking on tokens to select tree node
|
||||||
- Use local caching
|
- Use local caching
|
||||||
- Enter string/float/int literals
|
- Enter string/float/int literals
|
||||||
@@ -21,10 +43,7 @@ An improved version of the [old syntax editor][1].
|
|||||||
- ambiguity: (optionally) parse all the resulting linearizations/variants and point out those which are ambiguous
|
- ambiguity: (optionally) parse all the resulting linearizations/variants and point out those which are ambiguous
|
||||||
- try to retain subtree when replacing node
|
- try to retain subtree when replacing node
|
||||||
- add undo/redo (or back/forward) navigation
|
- add undo/redo (or back/forward) navigation
|
||||||
- structure the set of fridge magnets some more. Even though they
|
- structure fridge magnets some more (eg newline before the magnet whose first letter is different)
|
||||||
are alphabetically sorted, it's difficult to find the one that I want,
|
|
||||||
maybe put a newline before the magnet whose first letter is different
|
|
||||||
with respect to the previous magnet
|
|
||||||
- The formal-looking funs and cats are not linked/aligned to the linearizations.
|
- The formal-looking funs and cats are not linked/aligned to the linearizations.
|
||||||
Maybe a possible UI could be where the user is
|
Maybe a possible UI could be where the user is
|
||||||
clicking on the linearization (in a chosen language) and the tree is
|
clicking on the linearization (in a chosen language) and the tree is
|
||||||
|
|||||||
@@ -13,7 +13,20 @@ function Editor(server,opts) {
|
|||||||
|
|
||||||
// default values for options:
|
// default values for options:
|
||||||
this.options={
|
this.options={
|
||||||
target: "editor"
|
target: "editor",
|
||||||
|
initial: {
|
||||||
|
grammar: null,
|
||||||
|
startcat: null,
|
||||||
|
languages: null,
|
||||||
|
ast: null,
|
||||||
|
node_id: null
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
grammar_menu: true,
|
||||||
|
startcat_menu: true,
|
||||||
|
to_menu: true,
|
||||||
|
random_button: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply supplied options
|
// Apply supplied options
|
||||||
@@ -35,11 +48,14 @@ function Editor(server,opts) {
|
|||||||
this.server = server;
|
this.server = server;
|
||||||
this.ast = null;
|
this.ast = null;
|
||||||
this.grammar = null;
|
this.grammar = null;
|
||||||
|
this.startcat = null;
|
||||||
this.languages = [];
|
this.languages = [];
|
||||||
this.local = {}; // local settings which may override grammar
|
|
||||||
|
|
||||||
/* --- Main program, this gets things going ----------------------------- */
|
/* --- Main program, this gets things going ----------------------------- */
|
||||||
this.menu = new EditorMenu(this);
|
this.menu = new EditorMenu(this, this.options);
|
||||||
|
|
||||||
|
/* --- Apply supplied initial settings (if any) ------------------------- */
|
||||||
|
// if (this.options.initial.grammar)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,24 +81,25 @@ Editor.prototype.get_ast=function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Editor.prototype.get_startcat=function() {
|
Editor.prototype.get_startcat=function() {
|
||||||
return this.local.startcat || this.grammar.startcat;
|
return this.startcat || this.grammar.startcat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- These get called from EditorMenu, or some custom code */
|
/* --- These get called from EditorMenu, or some custom code */
|
||||||
|
|
||||||
Editor.prototype.change_grammar=function(grammar_info) {
|
Editor.prototype.change_grammar=function(grammar_info) {
|
||||||
with(this) {
|
var t = this;
|
||||||
grammar = grammar_info;
|
t.grammar = grammar_info;
|
||||||
local.startcat = null;
|
var startcat0 = t.options.initial.startcat
|
||||||
get_grammar_constructors(bind(start_fresh,this));
|
if (elem(startcat0, grammar_info.categories))
|
||||||
}
|
t.startcat = startcat0;
|
||||||
|
else
|
||||||
|
t.startcat = null;
|
||||||
|
t.get_grammar_constructors(bind(t.start_fresh,t));
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor.prototype.change_startcat=function(startcat) {
|
Editor.prototype.change_startcat=function(startcat) {
|
||||||
with(this) {
|
this.startcat = startcat;
|
||||||
local.startcat = startcat;
|
this.start_fresh();
|
||||||
start_fresh();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called after changing grammar or startcat
|
// Called after changing grammar or startcat
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ function EditorMenu(editor,opts) {
|
|||||||
/* --- Creating UI components ------------------------------------------- */
|
/* --- Creating UI components ------------------------------------------- */
|
||||||
this.container = editor.ui.menubar;
|
this.container = editor.ui.menubar;
|
||||||
this.ui = {
|
this.ui = {
|
||||||
|
grammar_menu: empty_id("select","grammar_menu"),
|
||||||
startcat_menu: empty("select"),
|
startcat_menu: empty("select"),
|
||||||
to_toggle: button("...", function(){
|
to_toggle: button("Languages...", function(){
|
||||||
var sel = t.ui.to_menu;
|
var sel = t.ui.to_menu;
|
||||||
if (sel.classList.contains("hidden"))
|
if (sel.classList.contains("hidden"))
|
||||||
sel.classList.remove("hidden")
|
sel.classList.remove("hidden")
|
||||||
@@ -35,12 +36,22 @@ function EditorMenu(editor,opts) {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
with(this.ui) {
|
with(this.ui) {
|
||||||
appendChildren(this.container, [text(" Startcat: "),startcat_menu]);
|
if (this.options.show.grammar_menu) {
|
||||||
appendChildren(this.container, [text(" To: "), to_toggle, to_menu]);
|
appendChildren(this.container, [text(" Grammar: "), grammar_menu]);
|
||||||
appendChildren(this.container, [clear_button, random_button]);
|
grammar_menu.onchange = bind(this.change_grammar,this);
|
||||||
// appendChildren(this.container, [clear_button]);
|
}
|
||||||
startcat_menu.onchange=bind(this.change_startcat,this);
|
if (this.options.show.startcat_menu) {
|
||||||
to_menu.onchange=bind(this.change_language,this);
|
appendChildren(this.container, [text(" Startcat: "), startcat_menu]);
|
||||||
|
startcat_menu.onchange = bind(this.change_startcat,this);
|
||||||
|
}
|
||||||
|
if (this.options.show.to_menu) {
|
||||||
|
appendChildren(this.container, [text(" To: "), to_toggle, to_menu]);
|
||||||
|
to_menu.onchange = bind(this.change_language,this);
|
||||||
|
}
|
||||||
|
appendChildren(this.container, [clear_button]);
|
||||||
|
if (this.options.show.random_button) {
|
||||||
|
appendChildren(this.container, [random_button]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Client state initialisation -------------------------------------- */
|
/* --- Client state initialisation -------------------------------------- */
|
||||||
@@ -53,12 +64,14 @@ function EditorMenu(editor,opts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Grammar menu --------------------------------------------------------- */
|
||||||
|
|
||||||
|
// Basically called once, when initializing
|
||||||
// Copied from minibar.js
|
// Copied from minibar.js
|
||||||
EditorMenu.prototype.show_grammarlist=function(dir,grammar_names,dir_count) {
|
EditorMenu.prototype.show_grammarlist=function(dir,grammar_names,dir_count) {
|
||||||
var t=this;
|
var t=this;
|
||||||
var first_time= !t.grammar_menu
|
var first_time=t.ui.grammar_menu.options.length == 0;
|
||||||
if(first_time) {
|
if(first_time) {
|
||||||
t.grammar_menu=empty_id("select","grammar_menu");
|
|
||||||
t.grammars=[];
|
t.grammars=[];
|
||||||
t.grammar_dirs=[];
|
t.grammar_dirs=[];
|
||||||
}
|
}
|
||||||
@@ -70,29 +83,12 @@ EditorMenu.prototype.show_grammarlist=function(dir,grammar_names,dir_count) {
|
|||||||
}
|
}
|
||||||
function opt(g) { return option(glabel(g),dir+g); }
|
function opt(g) { return option(glabel(g),dir+g); }
|
||||||
appendChildren(grammar_menu,map(opt,grammar_names));
|
appendChildren(grammar_menu,map(opt,grammar_names));
|
||||||
function pick() {
|
|
||||||
var grammar_url=grammar_menu.value
|
|
||||||
if(window.localStorage)
|
|
||||||
localStorage["gf.minibar.last_grammar"]=grammar_url;
|
|
||||||
t.select_grammar(grammar_url);
|
|
||||||
}
|
|
||||||
function pick_first_grammar() {
|
function pick_first_grammar() {
|
||||||
if(t.timeout) clearTimeout(t.timeout),t.timeout=null;
|
if(t.timeout) clearTimeout(t.timeout),t.timeout=null;
|
||||||
if(t.grammar_menu.length>1 && !t.grammar_menu.parentElement) {
|
var grammar0=t.options.initial.grammar;
|
||||||
t.grammar_menu.onchange=pick;
|
|
||||||
// insertFirst(t.menubar,button("i",bind(t.show_grammarinfo,t)))
|
|
||||||
insertFirst(t.container,t.grammar_menu);
|
|
||||||
insertFirst(t.container,text("Grammar: "));
|
|
||||||
}
|
|
||||||
var grammar0=t.options.initial_grammar
|
|
||||||
if(!grammar0 && window.localStorage) {
|
|
||||||
var last_grammar=localStorage["gf.minibar.last_grammar"];
|
|
||||||
if(last_grammar && elem(last_grammar,t.grammars))
|
|
||||||
grammar0=last_grammar;
|
|
||||||
}
|
|
||||||
if(!grammar0) grammar0=t.grammars[0];
|
if(!grammar0) grammar0=t.grammars[0];
|
||||||
t.grammar_menu.value=grammar0;
|
t.ui.grammar_menu.value=grammar0;
|
||||||
t.select_grammar(grammar0);
|
t.change_grammar();
|
||||||
}
|
}
|
||||||
// Wait at most 1.5s before showing the grammar menu.
|
// Wait at most 1.5s before showing the grammar menu.
|
||||||
if(first_time) t.timeout=setTimeout(pick_first_grammar,1500);
|
if(first_time) t.timeout=setTimeout(pick_first_grammar,1500);
|
||||||
@@ -101,9 +97,9 @@ EditorMenu.prototype.show_grammarlist=function(dir,grammar_names,dir_count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copied from minibar.js
|
// Copied from minibar.js
|
||||||
EditorMenu.prototype.select_grammar=function(grammar_url) {
|
EditorMenu.prototype.change_grammar=function() {
|
||||||
var t=this;
|
var t=this;
|
||||||
//debug("select_grammar ");
|
var grammar_url = t.ui.grammar_menu.value;
|
||||||
t.server.switch_to_other_grammar(grammar_url, function() {
|
t.server.switch_to_other_grammar(grammar_url, function() {
|
||||||
t.server.grammar_info(function(grammar){
|
t.server.grammar_info(function(grammar){
|
||||||
t.update_language_menu(t.ui.to_menu, grammar);
|
t.update_language_menu(t.ui.to_menu, grammar);
|
||||||
@@ -115,29 +111,63 @@ EditorMenu.prototype.select_grammar=function(grammar_url) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Start category menu -------------------------------------------------- */
|
||||||
|
|
||||||
|
// Called each time the current grammar is changed!
|
||||||
// Copied from minibar_input.js
|
// Copied from minibar_input.js
|
||||||
EditorMenu.prototype.update_startcat_menu=function(grammar) {
|
EditorMenu.prototype.update_startcat_menu=function(grammar) {
|
||||||
|
var t=this;
|
||||||
var menu=this.ui.startcat_menu;
|
var menu=this.ui.startcat_menu;
|
||||||
menu.innerHTML="";
|
menu.innerHTML="";
|
||||||
var cats=grammar.categories;
|
var cats=grammar.categories;
|
||||||
for(var cat in cats) menu.appendChild(option(cats[cat],cats[cat]))
|
for(var cat in cats) menu.appendChild(option(cats[cat],cats[cat]))
|
||||||
// var startcat=this.local.get("startcat") || grammar.startcat;
|
// var startcat=this.local.get("startcat") || grammar.startcat;
|
||||||
var startcat= grammar.startcat;
|
var startcat0 = t.options.initial.startcat;
|
||||||
if(startcat) menu.value=startcat;
|
if (elem(startcat0, cats))
|
||||||
else {
|
menu.value = startcat0;
|
||||||
insertFirst(menu,option("Default",""));
|
else
|
||||||
menu.value="";
|
menu.value = grammar.startcat;
|
||||||
}
|
// else {
|
||||||
|
// insertFirst(menu,option("Default",""));
|
||||||
|
// menu.value="";
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
EditorMenu.prototype.change_startcat=function () {
|
EditorMenu.prototype.change_startcat=function() {
|
||||||
var new_startcat = this.ui.startcat_menu.value;
|
var new_startcat = this.ui.startcat_menu.value;
|
||||||
this.editor.change_startcat(new_startcat);
|
this.editor.change_startcat(new_startcat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Langugage (to) menu -------------------------------------------------- */
|
||||||
|
|
||||||
|
// Called each time the current grammar is changed!
|
||||||
|
// Copied from minibar_support.js
|
||||||
|
EditorMenu.prototype.update_language_menu=function(menu,grammar) {
|
||||||
|
var t = this;
|
||||||
|
function langpart(conc,abs) { // langpart("FoodsEng","Foods") == "Eng"
|
||||||
|
return hasPrefix(conc,abs) ? conc.substr(abs.length) : conc;
|
||||||
|
}
|
||||||
|
// Replace the options in the menu with the languages in the grammar
|
||||||
|
var langs=grammar.languages;
|
||||||
|
menu.innerHTML="";
|
||||||
|
|
||||||
|
for(var i=0; i<langs.length; i++) {
|
||||||
|
var ln=langs[i].name;
|
||||||
|
if(!hasPrefix(ln,"Disamb")) {
|
||||||
|
var lp=langpart(ln,grammar.name);
|
||||||
|
var opt=option(lp,ln);
|
||||||
|
if (elem(lp, t.options.initial.languages)) {
|
||||||
|
opt.selected=true;
|
||||||
|
t.editor.languages.push(opt.value);
|
||||||
|
}
|
||||||
|
menu.appendChild(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
EditorMenu.prototype.change_language=function () {
|
EditorMenu.prototype.change_language=function() {
|
||||||
this.editor.languages = new Array();
|
this.editor.languages = new Array();
|
||||||
for (i in this.ui.to_menu.options) {
|
for (i in this.ui.to_menu.options) {
|
||||||
var opt = this.ui.to_menu.options[i];
|
var opt = this.ui.to_menu.options[i];
|
||||||
@@ -147,27 +177,3 @@ EditorMenu.prototype.change_language=function () {
|
|||||||
this.editor.update_linearisation();
|
this.editor.update_linearisation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copied from minibar_support.js
|
|
||||||
EditorMenu.prototype.update_language_menu=function(menu,grammar) {
|
|
||||||
|
|
||||||
function langpart(conc,abs) { // langpart("FoodsEng","Foods") == "Eng"
|
|
||||||
return hasPrefix(conc,abs) ? conc.substr(abs.length) : conc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the options in the menu with the languages in the grammar
|
|
||||||
var lang=grammar.languages;
|
|
||||||
menu.innerHTML="";
|
|
||||||
|
|
||||||
for(var i=0; i<lang.length; i++) {
|
|
||||||
var ln=lang[i].name;
|
|
||||||
if(!hasPrefix(ln,"Disamb")) {
|
|
||||||
var lp=langpart(ln,grammar.name);
|
|
||||||
menu.appendChild(option(lp,ln));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// insertFirst(menu,option("All","All"));
|
|
||||||
// menu.value="All";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user