Commit ceb27bf2 authored by Evaldas Latoškinas's avatar Evaldas Latoškinas Committed by Evan W. Patton

Implement join-with-separator block

Change-Id: I6d7899a36e7e2ee4dd748948a98ce6693af18650
parent b2d4a63c
...@@ -449,3 +449,22 @@ Blockly.Blocks['lists_lookup_in_pairs'] = { ...@@ -449,3 +449,22 @@ Blockly.Blocks['lists_lookup_in_pairs'] = {
}, },
typeblock: [{ translatedName: Blockly.Msg.LANG_LISTS_LOOKUP_IN_PAIRS_TITLE_LOOKUP_IN_PAIRS }] typeblock: [{ translatedName: Blockly.Msg.LANG_LISTS_LOOKUP_IN_PAIRS_TITLE_LOOKUP_IN_PAIRS }]
}; };
Blockly.Blocks['lists_join_with_separator'] = {
// Joins list items into a single string separated by specified separator
category : 'Lists',
helpUrl : Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_HELPURL,
init : function() {
this.setColour(Blockly.LIST_CATEGORY_HUE);
this.setOutput(true, Blockly.Blocks.Utilities.YailTypeToBlocklyType("text",Blockly.Blocks.Utilities.OUTPUT));
var checkTypeList = Blockly.Blocks.Utilities.YailTypeToBlocklyType("list",Blockly.Blocks.Utilities.INPUT);
var checkTypeText = Blockly.Blocks.Utilities.YailTypeToBlocklyType("text",Blockly.Blocks.Utilities.INPUT);
this.interpolateMsg(Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_INPUT,
['SEPARATOR', checkTypeText, Blockly.ALIGN_RIGHT],
['LIST', checkTypeList, Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setTooltip(Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_TOOLTIP);
this.setInputsInline(false);
},
typeblock: [{ translatedName: Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_TITLE }]
};
...@@ -432,6 +432,12 @@ Blockly.Drawer.defaultBlockXMLStrings = { ...@@ -432,6 +432,12 @@ Blockly.Drawer.defaultBlockXMLStrings = {
'<value name="NOTFOUND"><block type="text"><title name="TEXT">not found</title></block></value>' + '<value name="NOTFOUND"><block type="text"><title name="TEXT">not found</title></block></value>' +
'</block>' + '</block>' +
'</xml>'}, '</xml>'},
lists_join_with_separator: {xmlString:
'<xml>' +
'<block type="lists_join_with_separator">' +
'<value name="SEPARATOR"><block type="text"><title name="TEXT"></title></block></value>' +
'</block>' +
'</xml>'},
component_method: [ component_method: [
{matchingMutatorAttributes:{component_type:"TinyDB", method_name:"GetValue"}, {matchingMutatorAttributes:{component_type:"TinyDB", method_name:"GetValue"},
......
...@@ -300,7 +300,7 @@ Blockly.Yail['lists_from_csv_table'] = function() { ...@@ -300,7 +300,7 @@ Blockly.Yail['lists_from_csv_table'] = function() {
return [ code, Blockly.Yail.ORDER_ATOMIC ]; return [ code, Blockly.Yail.ORDER_ATOMIC ];
}; };
Blockly.Yail['lists_lookup_in_pairs'] = function() { Blockly.Yail['lists_lookup_in_pairs'] = function() {
// Lookup in pairs in list of lists (key, value). // Lookup in pairs in list of lists (key, value).
var argument0 = Blockly.Yail.valueToCode(this, 'KEY', Blockly.Yail.ORDER_NONE) || Blockly.Yail.YAIL_FALSE; var argument0 = Blockly.Yail.valueToCode(this, 'KEY', Blockly.Yail.ORDER_NONE) || Blockly.Yail.YAIL_FALSE;
var argument1 = Blockly.Yail.valueToCode(this, 'LIST', Blockly.Yail.ORDER_NONE) || Blockly.Yail.emptyListCode; var argument1 = Blockly.Yail.valueToCode(this, 'LIST', Blockly.Yail.ORDER_NONE) || Blockly.Yail.emptyListCode;
...@@ -312,4 +312,18 @@ Blockly.Yail['lists_from_csv_table'] = function() { ...@@ -312,4 +312,18 @@ Blockly.Yail['lists_from_csv_table'] = function() {
code = code + "any list any" + Blockly.Yail.YAIL_CLOSE_COMBINATION + Blockly.Yail.YAIL_SPACER; code = code + "any list any" + Blockly.Yail.YAIL_CLOSE_COMBINATION + Blockly.Yail.YAIL_SPACER;
code = code + Blockly.Yail.YAIL_SPACER + Blockly.Yail.YAIL_DOUBLE_QUOTE + "lookup in pairs" + Blockly.Yail.YAIL_DOUBLE_QUOTE + Blockly.Yail.YAIL_CLOSE_COMBINATION; code = code + Blockly.Yail.YAIL_SPACER + Blockly.Yail.YAIL_DOUBLE_QUOTE + "lookup in pairs" + Blockly.Yail.YAIL_DOUBLE_QUOTE + Blockly.Yail.YAIL_CLOSE_COMBINATION;
return [ code, Blockly.Yail.ORDER_ATOMIC ]; return [ code, Blockly.Yail.ORDER_ATOMIC ];
}; };
Blockly.Yail['lists_join_with_separator'] = function() {
// Joins list items into a string separated by specified separator
var argument0 = Blockly.Yail.valueToCode(this, 'SEPARATOR', Blockly.Yail.ORDER_NONE) || "\"\"";
var argument1 = Blockly.Yail.valueToCode(this, 'LIST', Blockly.Yail.ORDER_NONE) || Blockly.Yail.emptyListCode;
var code = Blockly.Yail.YAIL_CALL_YAIL_PRIMITIVE + "yail-list-join-with-separator" + Blockly.Yail.YAIL_SPACER;
code = code + Blockly.Yail.YAIL_OPEN_COMBINATION + Blockly.Yail.YAIL_LIST_CONSTRUCTOR + Blockly.Yail.YAIL_SPACER;
code = code + argument1 + Blockly.Yail.YAIL_SPACER;
code = code + argument0 + Blockly.Yail.YAIL_CLOSE_COMBINATION;
code = code + Blockly.Yail.YAIL_SPACER + Blockly.Yail.YAIL_QUOTE;
code = code + Blockly.Yail.YAIL_OPEN_COMBINATION + "list" + Blockly.Yail.YAIL_SPACER + "text" + Blockly.Yail.YAIL_CLOSE_COMBINATION;
code = code + Blockly.Yail.YAIL_SPACER + Blockly.Yail.YAIL_DOUBLE_QUOTE + "join with separator" + Blockly.Yail.YAIL_DOUBLE_QUOTE + Blockly.Yail.YAIL_CLOSE_COMBINATION;
return [ code, Blockly.Yail.ORDER_ATOMIC ];
};
...@@ -901,6 +901,14 @@ Blockly.Msg.en.switch_language_to_english = { ...@@ -901,6 +901,14 @@ Blockly.Msg.en.switch_language_to_english = {
Blockly.Msg.LANG_LISTS_LOOKUP_IN_PAIRS_INPUT = 'look up in pairs key %1 pairs %2 notFound %3'; Blockly.Msg.LANG_LISTS_LOOKUP_IN_PAIRS_INPUT = 'look up in pairs key %1 pairs %2 notFound %3';
Blockly.Msg.LANG_LISTS_LOOKUP_IN_PAIRS_TOOLTIP = 'Returns the value associated with the key in the list of pairs'; Blockly.Msg.LANG_LISTS_LOOKUP_IN_PAIRS_TOOLTIP = 'Returns the value associated with the key in the list of pairs';
// Join With Separator block
Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_HELPURL = '/reference/blocks/lists.html#joinwithseparator';
Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_TITLE = 'join with separator';
Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_SEPARATOR = 'separator';
Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_LIST = 'list';
Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_INPUT = 'join items using separator %1 list %2';
Blockly.Msg.LANG_LISTS_JOIN_WITH_SEPARATOR_TOOLTIP = 'Returns text with list elements joined with separator';
/*Blockly.Msg.LANG_LISTS_INDEX_OF_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; /*Blockly.Msg.LANG_LISTS_INDEX_OF_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';
Blockly.Msg.LANG_LISTS_INDEX_OF_TITLE_FIND = 'find'; Blockly.Msg.LANG_LISTS_INDEX_OF_TITLE_FIND = 'find';
Blockly.Msg.LANG_LISTS_INDEX_OF_INPUT_OCCURRENCE = 'occurrence of item'; Blockly.Msg.LANG_LISTS_INDEX_OF_INPUT_OCCURRENCE = 'occurrence of item';
......
...@@ -1777,7 +1777,10 @@ Blockly.Versioning.AllUpgradeMaps = ...@@ -1777,7 +1777,10 @@ Blockly.Versioning.AllUpgradeMaps =
23: "noUpgrade", 23: "noUpgrade",
// AI2: In BLOCKS_LANGUAGE_VERSION 24, added List Reverse Block // AI2: In BLOCKS_LANGUAGE_VERSION 24, added List Reverse Block
24: "noUpgrade" 24: "noUpgrade",
// AI2: In BLOCKS_LANGUAGE_VERSION 25, added Join With Separator Block
25: "noUpgrade"
}, // End Language upgraders }, // End Language upgraders
......
...@@ -74,7 +74,11 @@ public class BlocklyCodeGeneratorTest extends TestCase { ...@@ -74,7 +74,11 @@ public class BlocklyCodeGeneratorTest extends TestCase {
assertEquals("true", result.toString()); assertEquals("true", result.toString());
} }
public void testListsJoinWithSeparator() throws Exception {
String result = BlocklyTestUtils.generatorTest(
testpath + "/tests/com/google/appinventor/generators_unit/listsJoinWithSeparatorTest.js");
assertEquals("true", result.toString());
}
// add more unit tests here // add more unit tests here
......
// Copyright 2011-2013 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
/**
* Unit test for "make a list" block Yail generator
*
* Author: Hal Abelson (hal@mit.edu)
*/
// This file runs a unit test for block Yail generation. It generates the
// Yail for a block and checks wheither that contains the expected Yail
// (modulo whitespace). This file illustrates how to test the "make a list"
// block (in the verison where there are no arguments). Use this file (minus the
// comments), as a template for creating other generator unit tests.
// You can insert the test into
// blocklyeditor/tests/com/google/appinventor/blocklyeditor/BlocklyCodeGeneratorTest.java
// to include it in the suite of unit tests.
// You can also run this single test from the command line in the
// appinventor directory by executing the command
// phantomJS blocklyeditor/tests/com/google/appinventor/generators_unit/listsCreateWithTest.js
// To create a generator test, you need to define four values:
// (1) expected: the correct yail string for the block with all slots empty
// delayedGenerator: The block Yail generation function (delayed)
// blockName: name of the block
// doesReturn: true if the block returns a value, false otherwise
// (2) We pass the generator function delayed, because the symbol Blockly
// is not defined when the required page is loaded, but it _will_ be defined after
// load, which is why we can force the value inside page.evaluate
// evaluation function. See the definition of generator_test_main_routine.js
// To find the correct value of expected, open the blocks pane, drag out the block
// and hightlight it (keep the sockets empty), then start the debugger and run in the console:
// bs = Blocklies['5629499534213120_Screen1']; // or whatever the right index is
// bs.Yail.lists_create_with.call(bs.selected);
// Alternatively, you can get the array of blocks on the screen with
// Blocklies["5066549580791808_Screen1"].mainWorkspace.getTopBlocks();
// Get the appropraite block, and then run
// Blockly.Yail.BlocktoCode1(block)
// (3) Whether or not the block returns a value
// (4) If the block uses a dropdown to specify the operator,
// pass in the tag for that operator (as defined by the generator).
// If no dropdown, pass in false
////////////////////////////////////////
// These four variables are all you need to define to create a test
////////////////////////////////////////
var expected =
"(call-yail-primitive yail-list-join-with-separator (*list-for-runtime* (call-yail-primitive make-yail-list (*list-for-runtime* ) '() \"make a list\") \"\") '(list text) \"join with separator\")";
var delayedGenerator = function () { return Blockly.Yail.lists_join_with_separator; } ;
var blockName = 'lists_join_with_separator';
var doesReturn = true;
var dropdownOp = false;
////////////////////////////////////////
// The rest of this page is common to all tests.
////////////////////////////////////////
// PhantomJS page object to open and load an URL - unfortunately we need to fully load Blockly
var page = require('webpage').create();
// Some debugging from PhantomJS
page.onConsoleMessage = function (msg) { console.log(msg); };
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
console.log(' ', item.file, ':', item.line);
});
};
var mainTest = require('./generator_test_mainRoutine.js');
mainTest.execute();
...@@ -1904,6 +1904,7 @@ Block name Kawa implementation ...@@ -1904,6 +1904,7 @@ Block name Kawa implementation
- is list? (yail-list? object) - is list? (yail-list? object)
- is empty? (yail-list-empty? yail-list) - is empty? (yail-list-empty? yail-list)
- lookup in pairs (yail-alist-lookup key yail-list-of-pairs default) - lookup in pairs (yail-alist-lookup key yail-list-of-pairs default)
- join with separator (yail-list-join-with-separator yail-list separator)
Lists in App Inventor are implemented as "Yail lists". A Yail list is Lists in App Inventor are implemented as "Yail lists". A Yail list is
a Java pair whose car is a distinguished token a Java pair whose car is a distinguished token
...@@ -2331,7 +2332,11 @@ list, use the make-yail-list constructor with no arguments. ...@@ -2331,7 +2332,11 @@ list, use the make-yail-list constructor with no arguments.
(and (yail-list? candidate-pair) (and (yail-list? candidate-pair)
(= (length (yail-list-contents candidate-pair)) 2))) (= (length (yail-list-contents candidate-pair)) 2)))
;;; Joins list elements into a string separated by separator
;;; Important to convert yail-list to yail-list-contents so that *list*
;;; is not included as first string.
(define (yail-list-join-with-separator yail-list separator)
(join-strings (yail-list-contents yail-list) separator))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
......
...@@ -448,8 +448,10 @@ public class YaVersion { ...@@ -448,8 +448,10 @@ public class YaVersion {
// - BLOCKS_LANGUAGE_VERSION was incremented to 24 // - BLOCKS_LANGUAGE_VERSION was incremented to 24
// For YOUNG_ANDROID_VERSION 180: // For YOUNG_ANDROID_VERSION 180:
// - VIDEOPLAYER_COMPONENT_VERSION was incremented to 6 // - VIDEOPLAYER_COMPONENT_VERSION was incremented to 6
// For YOUNG_ANDROID_VERSION 181:
// - BLOCKS_LANGUAGE_VERSION was incremented to 25
public static final int YOUNG_ANDROID_VERSION = 180; public static final int YOUNG_ANDROID_VERSION = 181;
// ............................... Blocks Language Version Number ............................... // ............................... Blocks Language Version Number ...............................
...@@ -517,8 +519,10 @@ public class YaVersion { ...@@ -517,8 +519,10 @@ public class YaVersion {
// - Bitwise and, ior, and xor blocks were added. // - Bitwise and, ior, and xor blocks were added.
// For BLOCKS_LANGUAGE_VERSION 24: // For BLOCKS_LANGUAGE_VERSION 24:
// - List reverse block was added. // - List reverse block was added.
// For BLOCKS_LANGUAGE_VERSION 25:
// - List join with separator block was added.
public static final int BLOCKS_LANGUAGE_VERSION = 24; public static final int BLOCKS_LANGUAGE_VERSION = 25;
// ................................. Component Version Numbers .................................. // ................................. Component Version Numbers ..................................
......
...@@ -226,6 +226,7 @@ jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","ajaxPageState": ...@@ -226,6 +226,7 @@ jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","ajaxPageState":
<li><a href="#listfromcsvrow">list from csv row</a></li> <li><a href="#listfromcsvrow">list from csv row</a></li>
<li><a href="#listfromcsvtable">list from csv table</a></li> <li><a href="#listfromcsvtable">list from csv table</a></li>
<li><a href="#lookupinpairs">lookup in pairs</a></li> <li><a href="#lookupinpairs">lookup in pairs</a></li>
<li><a href="#joinwithseparator">join with separator</a></li>
</ul><h4><em>Need additional help understanding lists? Check out <a href="../concepts/lists.html">making lists</a> on the Concepts page.</em></h4> </ul><h4><em>Need additional help understanding lists? Check out <a href="../concepts/lists.html">making lists</a> on the Concepts page.</em></h4>
<h3 id="emptylist">create empty list</h3> <h3 id="emptylist">create empty list</h3>
<p><img src="images/lists/emptylist.png" /></p> <p><img src="images/lists/emptylist.png" /></p>
...@@ -307,6 +308,10 @@ Here <em>pairs</em> must be a list of pairs, that is, a list where each element ...@@ -307,6 +308,10 @@ Here <em>pairs</em> must be a list of pairs, that is, a list where each element
element. For example, if the list is ((a apple) (d dragon) (b boxcar) (cat 100)) then looking up 'b' will return 'boxcar'.<br /> element. For example, if the list is ((a apple) (d dragon) (b boxcar) (cat 100)) then looking up 'b' will return 'boxcar'.<br />
If there is no such pair in the list, then the <em>lookup in pairs</em> will return the <em>notFound</em> result. If pairs is not a list of<br /> If there is no such pair in the list, then the <em>lookup in pairs</em> will return the <em>notFound</em> result. If pairs is not a list of<br />
pairs, then the operation will signal an error.</p> pairs, then the operation will signal an error.</p>
<h3 id="joinwithseparator">join with separator</h3>
<p><img src="images/lists/joinwithseparator.png" /></p>
<p>Joins all elements in the specified list by the specified separator, producing text as a result.<br />
By default, the separator is an empty string ("")</p>
</div></div></div> </div> </div></div></div> </div>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment