-
Notifications
You must be signed in to change notification settings - Fork 88
Setting up a New Language in Waterbear
This page is intended to help you to understand everything required for getting a new language with no Waterbear support running in Waterbear.
To begin you should start by creating a new directory which will house all of your language specific config files. This file structure should look like this:
waterbear
└── languages
└── myNewLanguage
├──blocks
├──examples
├──templates
| ├──examples.html
| └──stage.html
├──config.json
├──ide.js
├──myNewLang.css
├──~index.html
├──~runtime.html
└──runtime.js
"~" marks files that are automatically generated by build and shouldn't be created by hand or edited.
##Getting Started To get started you need at minimum to create
- blocks
- templates
- examples.html
- stage.html
- config.json
- myNewLang.css
- ide.js
The folder blocks holds your block definitions. Information on how to create block definitions can be found here.
The examples file holds menu definitions for the examples that you include in the examples folder. They are of the form:
<li><button class="load-example" data-example="EXAMPLE_FILE_NAME">Examples Name</button></li>
This file can be left empty.
Stage.html allows you to define the Stage which is where your languages code will be output if it runs in the browser. A skeleton file for this looks like:
<div class="results">
<div class="scripts_text_view"></div>
</div>
config.json holds information for the build script about your language. The file takes the form of:
{
"runsInBrowser": true, ;;can be true or false dictates whether the language will run in the browser or just display code
"plugins": ["blocktype1", "blocktype2], ;;a list of all the block categories you have defined
"runtimeLibs": [], ;;list of runtime libraries you use during runtime of code
;;a good example of this would be if you are using a language to JS interpreter
;;you would put the lib here
"styles": ["highlight-github"], ;;styles for the code. can use highlight-github or nothing
"ideLibs": ["ajax", "beautify", "highlight", "events.min"] ;;libraries used by the IDE
;;include at least ajax and events.min
}
This file should have an entry for how to color each block group in the language and value group. The file should look like this:
/* block and border colours for different groups of blocks */
//generic block group called "control"
.control, .control.holder{
border-color: hsl(296, 65%, 57%);
background-color: hsl(296, 65%, 77%);
}
/* Border colours for type values and sockets */
//set what the "any" type looks like
.any, .any .holder{
border-color: gray;
}
ide.js is the main file you will be working with and will look as follows:
(function(wb,Event){
// Add some utilities
'use strict';
wb.wrap = function(script){}; //This function is used to wrap necessary additions around the script
//This function is used to setup running the script
//it is called automatically on change of script
//should always end with calling runScript
function runCurrentScripts(force){
if (!(wb.autorun || force)){
// false alarm, we were notified of a script change, but user hasn't asked us to restart script
return;
}
document.body.classList.add('running');
if (!wb.scriptLoaded){
console.log('not ready to run script yet, waiting');
return;
}else{
console.log('ready to run script, let us proceed to the running of said script');
}
var blocks = wb.findAll(document.body, '.scripts_workspace'); //gets all the blocks
//UPDATE THINGS NECESSARY FOR RUNNING
wb.runScript( wb.prettyScript(blocks) ); //actually run the script
}
wb.runCurrentScripts = runCurrentScripts;
if (!wb.iframeReady){
document.querySelector('.stageframe').addEventListener('load', function(event){
console.log('iframe ready, waiting: %s', !!wb.iframewaiting);
if (wb.iframewaiting){
wb.iframewaiting();
}
wb.iframewaiting = null;
}, false);
}
//this function takes in the script and should actually run it and produce
//output to the iframe Stage
wb.runScript = function(script){};
function clearStage(event){} //this function should include all functionality required to clear the Stage
wb.clearStage = clearStage;
Event.on('.clear-stage', 'click', null, clearStage);
Event.on('.edit-script', 'click', null, clearStage);
//this function produces the script from the blocks
wb.prettyScript = function(elements){
return elements.map(function(elem){
return wb.codeFromBlock(elem);
}).join('');
};
//this function writes the script to view so that the code can be seen
wb.writeScript = function(elements, view){
view.innerHTML = '<pre class="language-javascript">' + wb.prettyScript(elements) + '</pre>';
};
// End UI section
//This is a list of some of the choices you can have for choiceLists you can create for
//your blocks. This example is taken from the JS ide file
wb.choiceLists = {
boolean: ['true', 'false'],
keys: 'abcdefghijklmnopqrstuvwxyz0123456789*+-./'
.split('').concat(['up', 'down', 'left', 'right',
'backspace', 'tab', 'return', 'shift', 'ctrl', 'alt',
'pause', 'capslock', 'esc', 'space', 'pageup', 'pagedown',
'end', 'home', 'insert', 'del', 'numlock', 'scroll', 'meta']),
blocktypes: ['step', 'expression', 'context', 'eventhandler', 'asset'],
types: ['string', 'number', 'boolean', 'array', 'object', 'function', 'any'],
rettypes: ['none', 'string', 'number', 'boolean', 'array', 'object', 'function', 'any']
};
Event.on('.socket input', 'click', null, function(event){
event.wbTarget.focus();
event.wbTarget.select();
});
})(wb, Event);
All of the functions in this skeleton should be included to make sure a language runs properly.
Now that you have a (hopefully) working setup of files you should be able to start up your language. First start by building your language by running ./bin/build
. After you have built your language you can run it by going to routetohost/myNewLanguage.html
. If using a local python server you should be able to connect using localhost:8000/myNewLanguage.html
.
If you haven't made any changes to the skeleton files this will not look very exciting you should have no blocks and no running environment for your code even if you had block definitions. However you have taken the first steps to creating a new language! From here if you plan to have the language run in browser you should work on getting runScript() working. After your code can run in browser (or if it isn't going to) block definitions should be created to test your implementation of runScript(). a good test block file is:
(function(wb){
'use strict';
wb.menu(
{
"sectionkey": "control",
"name": "Control",
"help": "Basic Control blocks for testing",
"blocks": [
{
"blocktype": "step",
"id": "eec0910c-be04-407f-9536-f246a65222b7",
"script": "{{1}}",
"help": "Overall control block",
"sockets": [
{
"name": "",
"type": "any"
}
]
}
]
});
})(wb);
This should be saved as "controls_blockmenu.js". You should also make sure you have a copy of the example myNewLang.css file shown on this page for this to work. The block defined in this file will take any input so if you want to test your implementation before doing any more work you can just type language code into this block to make sure your runScript() is working properly.
Now that you have a basic implementation some more files can be covered.
Now that your language is working you can place saved .json files into the examples folder and add an entry in examples.html in the templates folder to have them show up in the menu for running.
runtime.js allows you to establish all of the functions your code will need at runtime. An excellent example of this can be found in the JavaScript implementation.