New blocks text_count, text_replace, and text_reverse (#830)

Includes generators for all languages and units tests on those generators.
This commit is contained in:
Tim Dawborn
2017-01-21 11:08:27 +11:00
committed by Andrew n marshall
parent fb0f1b05dd
commit 34750bccd8
12 changed files with 935 additions and 9 deletions

View File

@@ -689,3 +689,90 @@ Blockly.Blocks['text_prompt'] = {
mutationToDom: Blockly.Blocks['text_prompt_ext'].mutationToDom,
domToMutation: Blockly.Blocks['text_prompt_ext'].domToMutation
};
Blockly.Blocks['text_count'] = {
/**
* Block for counting how many times one string appears within another string.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.TEXT_COUNT_MESSAGE0,
"args0": [
{
"type": "input_value",
"name": "SUB",
"check": "String"
},
{
"type": "input_value",
"name": "TEXT",
"check": "String"
}
],
"output": "Number",
"inputsInline": true,
"colour": Blockly.Blocks.math.HUE,
"tooltip": Blockly.Msg.TEXT_COUNT_TOOLTIP,
"helpUrl": Blockly.Msg.TEXT_COUNT_HELPURL
});
}
};
Blockly.Blocks['text_replace'] = {
/**
* Block for replacing one string with another in the text.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.TEXT_REPLACE_MESSAGE0,
"args0": [
{
"type": "input_value",
"name": "FROM",
"check": "String"
},
{
"type": "input_value",
"name": "TO",
"check": "String"
},
{
"type": "input_value",
"name": "TEXT",
"check": "String"
},
],
"output": "String",
"inputsInline": true,
"colour": Blockly.Blocks.texts.HUE,
"tooltip": Blockly.Msg.TEXT_REPLACE_TOOLTIP,
"helpUrl": Blockly.Msg.TEXT_REPLACE_HELPURL
});
}
};
Blockly.Blocks['text_reverse'] = {
/**
* Block for reversing a string.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.TEXT_REVERSE_MESSAGE0,
"args0": [
{
"type": "input_value",
"name": "TEXT",
"check": "String"
},
],
"output": "String",
"inputsInline": true,
"colour": Blockly.Blocks.texts.HUE,
"tooltip": Blockly.Msg.TEXT_REVERSE_TOOLTIP,
"helpUrl": Blockly.Msg.TEXT_REVERSE_HELPURL
});
}
};

View File

@@ -295,3 +295,53 @@ Blockly.Dart['text_prompt_ext'] = function(block) {
};
Blockly.Dart['text_prompt'] = Blockly.Dart['text_prompt_ext'];
Blockly.Dart['text_count'] = function(block) {
var text = Blockly.Dart.valueToCode(block, 'TEXT',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
var sub = Blockly.Dart.valueToCode(block, 'SUB',
Blockly.Dart.ORDER_NONE) || '\'\'';
// Substring count is not a native Dart function. Define one.
var functionName = Blockly.Dart.provideFunction_(
'text_count',
['int ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(String haystack, String needle) {',
' if (needle.length == 0) {',
' return haystack.length + 1;',
' }',
' int index = 0;',
' int count = 0;',
' while (index != -1) {',
' index = haystack.indexOf(needle, index);',
' if (index != -1) {',
' count++;',
' index += needle.length;',
' }',
' }',
' return count;',
'}']);
var code = functionName + '(' + text + ', ' + sub + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['text_replace'] = function(block) {
var text = Blockly.Dart.valueToCode(block, 'TEXT',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
var from = Blockly.Dart.valueToCode(block, 'FROM',
Blockly.Dart.ORDER_NONE) || '\'\'';
var to = Blockly.Dart.valueToCode(block, 'TO',
Blockly.Dart.ORDER_NONE) || '\'\'';
var code = text + '.replaceAll(' + from + ', ' + to + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['text_reverse'] = function(block) {
// There isn't a sensible way to do this in Dart. See:
// http://stackoverflow.com/a/21613700/3529104
// Implementing something is possibly better than not implementing anything?
var text = Blockly.Dart.valueToCode(block, 'TEXT',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
var code = 'new String.fromCharCodes(' + text + '.runes.toList().reversed)';
// XXX What should the operator precedence be for a `new`?
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};

View File

@@ -302,3 +302,51 @@ Blockly.JavaScript['text_prompt_ext'] = function(block) {
};
Blockly.JavaScript['text_prompt'] = Blockly.JavaScript['text_prompt_ext'];
Blockly.JavaScript['text_count'] = function(block) {
var text = Blockly.JavaScript.valueToCode(block, 'TEXT',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
var sub = Blockly.JavaScript.valueToCode(block, 'SUB',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
var functionName = Blockly.JavaScript.provideFunction_(
'textCount',
['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(haystack, needle) {',
' if (needle.length === 0) {',
' return haystack.length + 1;',
' } else {',
' return haystack.split(needle).length - 1;',
' }',
'}']);
var code = functionName + '(' + text + ', ' + sub + ')';
return [code, Blockly.JavaScript.ORDER_SUBTRACTION];
};
Blockly.JavaScript['text_replace'] = function(block) {
var text = Blockly.JavaScript.valueToCode(block, 'TEXT',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
var from = Blockly.JavaScript.valueToCode(block, 'FROM',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
var to = Blockly.JavaScript.valueToCode(block, 'TO',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
// The regex escaping code below is taken from the implementation of
// goog.string.regExpEscape.
var functionName = Blockly.JavaScript.provideFunction_(
'textReplace',
['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(haystack, needle, replacement) {',
' needle = ' +
'needle.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g,"\\\\$1")',
' .replace(/\\x08/g,"\\\\x08");',
' return haystack.replace(new RegExp(needle, \'g\'), replacement);',
'}']);
var code = functionName + '(' + text + ', ' + from + ', ' + to + ')';
return [code, Blockly.JavaScript.ORDER_MEMBER];
};
Blockly.JavaScript['text_reverse'] = function(block) {
var text = Blockly.JavaScript.valueToCode(block, 'TEXT',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
var code = text + '.split(\'\').reverse().join(\'\')';
return [code, Blockly.JavaScript.ORDER_MEMBER];
};

View File

@@ -292,3 +292,70 @@ Blockly.Lua['text_prompt_ext'] = function(block) {
};
Blockly.Lua['text_prompt'] = Blockly.Lua['text_prompt_ext'];
Blockly.Lua['text_count'] = function(block) {
var text = Blockly.Lua.valueToCode(block, 'TEXT',
Blockly.Lua.ORDER_NONE) || '\'\'';
var sub = Blockly.Lua.valueToCode(block, 'SUB',
Blockly.Lua.ORDER_NONE) || '\'\'';
var functionName = Blockly.Lua.provideFunction_(
'text_count',
['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_
+ '(haystack, needle)',
' if #needle == 0 then',
' return #haystack + 1',
' end',
' local i = 1',
' local count = 0',
' while true do',
' i = string.find(haystack, needle, i, true)',
' if i == nil then',
' break',
' end',
' count = count + 1',
' i = i + #needle',
' end',
' return count',
'end',
]);
var code = functionName + '(' + text + ', ' + sub + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
Blockly.Lua['text_replace'] = function(block) {
var text = Blockly.Lua.valueToCode(block, 'TEXT',
Blockly.Lua.ORDER_NONE) || '\'\'';
var from = Blockly.Lua.valueToCode(block, 'FROM',
Blockly.Lua.ORDER_NONE) || '\'\'';
var to = Blockly.Lua.valueToCode(block, 'TO',
Blockly.Lua.ORDER_NONE) || '\'\'';
var functionName = Blockly.Lua.provideFunction_(
'text_replace',
['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_
+ '(haystack, needle, replacement)',
' local buf = {}',
' local i = 1',
' while i <= #haystack do',
' if string.sub(haystack, i, i + #needle - 1) == needle then',
' for j = 1, #replacement do',
' table.insert(buf, string.sub(replacement, j, j))',
' end',
' i = i + #needle',
' else',
' table.insert(buf, string.sub(haystack, i, i))',
' i = i + 1',
' end',
' end',
' return table.concat(buf)',
'end',
]);
var code = functionName + '(' + text + ', ' + from + ', ' + to + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
Blockly.Lua['text_reverse'] = function(block) {
var text = Blockly.Lua.valueToCode(block, 'TEXT',
Blockly.Lua.ORDER_HIGH) || '\'\'';
var code = 'string.reverse(' + text + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};

View File

@@ -248,3 +248,32 @@ Blockly.PHP['text_prompt_ext'] = function(block) {
};
Blockly.PHP['text_prompt'] = Blockly.PHP['text_prompt_ext'];
Blockly.PHP['text_count'] = function(block) {
var text = Blockly.PHP.valueToCode(block, 'TEXT',
Blockly.PHP.ORDER_MEMBER) || '\'\'';
var sub = Blockly.PHP.valueToCode(block, 'SUB',
Blockly.PHP.ORDER_NONE) || '\'\'';
var code = 'strlen(' + sub + ') === 0'
+ ' ? strlen(' + text + ') + 1'
+ ' : substr_count(' + text + ', ' + sub + ')';
return [code, Blockly.PHP.ORDER_CONDITIONAL];
};
Blockly.PHP['text_replace'] = function(block) {
var text = Blockly.PHP.valueToCode(block, 'TEXT',
Blockly.PHP.ORDER_MEMBER) || '\'\'';
var from = Blockly.PHP.valueToCode(block, 'FROM',
Blockly.PHP.ORDER_NONE) || '\'\'';
var to = Blockly.PHP.valueToCode(block, 'TO',
Blockly.PHP.ORDER_NONE) || '\'\'';
var code = 'str_replace(' + from + ', ' + to + ', ' + text + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['text_reverse'] = function(block) {
var text = Blockly.PHP.valueToCode(block, 'TEXT',
Blockly.PHP.ORDER_MEMBER) || '\'\'';
var code = 'strrev(' + text + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};

View File

@@ -251,3 +251,30 @@ Blockly.Python['text_prompt_ext'] = function(block) {
};
Blockly.Python['text_prompt'] = Blockly.Python['text_prompt_ext'];
Blockly.Python['text_count'] = function(block) {
var text = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_MEMBER) || '\'\'';
var sub = Blockly.Python.valueToCode(block, 'SUB',
Blockly.Python.ORDER_NONE) || '\'\'';
var code = text + '.count(' + sub + ')';
return [code, Blockly.Python.ORDER_MEMBER];
};
Blockly.Python['text_replace'] = function(block) {
var text = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_MEMBER) || '\'\'';
var from = Blockly.Python.valueToCode(block, 'FROM',
Blockly.Python.ORDER_NONE) || '\'\'';
var to = Blockly.Python.valueToCode(block, 'TO',
Blockly.Python.ORDER_NONE) || '\'\'';
var code = text + '.replace(' + from + ', ' + to + ')';
return [code, Blockly.Python.ORDER_MEMBER];
};
Blockly.Python['text_reverse'] = function(block) {
var text = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_MEMBER) || '\'\'';
var code = text + '[::-1]';
return [code, Blockly.Python.ORDER_MEMBER];
};

View File

@@ -1,7 +1,7 @@
{
"@metadata": {
"author": "Ellen Spertus <ellen.spertus@gmail.com>",
"lastupdated": "2017-01-12 13:53:04.889198",
"lastupdated": "2017-01-18 10:58:30.631169",
"locale": "en",
"messagedocumentation" : "qqq"
},
@@ -253,6 +253,15 @@
"TEXT_PROMPT_TYPE_NUMBER": "prompt for number with message",
"TEXT_PROMPT_TOOLTIP_NUMBER": "Prompt for user for a number.",
"TEXT_PROMPT_TOOLTIP_TEXT": "Prompt for user for some text.",
"TEXT_COUNT_MESSAGE0": "count %1 in %2",
"TEXT_COUNT_HELPURL": "",
"TEXT_COUNT_TOOLTIP": "Count how many times a string occurs in another string.",
"TEXT_REPLACE_MESSAGE0": "replace %1 with %2 in %3",
"TEXT_REPLACE_HELPURL": "",
"TEXT_REPLACE_TOOLTIP": "Replace a string within another string.",
"TEXT_REVERSE_MESSAGE0": "reverse %1",
"TEXT_REVERSE_HELPURL": "",
"TEXT_REVERSE_TOOLTIP": "Reverses the characters in a string.",
"LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list",
"LISTS_CREATE_EMPTY_TITLE": "create empty list",
"LISTS_CREATE_EMPTY_TOOLTIP": "Returns a list, of length 0, containing no data records",

View File

@@ -1,11 +1,4 @@
{
"@metadata": {
"authors": [
"Espertus",
"Liuxinyu970226",
"Shirayuki"
]
},
"VARIABLES_DEFAULT_NAME": "default name - A simple, general default name for a variable, preferably short. For more context, see [[Translating:Blockly#infrequent_message_types]].\n{{Identical|Item}}",
"TODAY": "button text - Button that sets a calendar to today's date.\n{{Identical|Today}}",
"DUPLICATE_BLOCK": "context menu - Make a copy of the selected block (and any blocks it contains).\n{{Identical|Duplicate}}",
@@ -254,6 +247,15 @@
"TEXT_PROMPT_TYPE_NUMBER": "dropdown - Specifies that a number should be requested from the user with the following message. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].",
"TEXT_PROMPT_TOOLTIP_NUMBER": "dropdown - Precedes the message with which the user should be prompted for a number. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].",
"TEXT_PROMPT_TOOLTIP_TEXT": "dropdown - Precedes the message with which the user should be prompted for some text. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].",
"TEXT_COUNT_MESSAGE0": "message0 interpolation string",
"TEXT_COUNT_HELPURL": "url - Information about counting how many times a string appears in another string.",
"TEXT_COUNT_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].",
"TEXT_REPLACE_MESSAGE0": "message0 interpolation string",
"TEXT_REPLACE_HELPURL": "url - Information about replacing a string within another string.",
"TEXT_REPLACE_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].",
"TEXT_REVERSE_MESSAGE0": "message0 interpolation string",
"TEXT_REVERSE_HELPURL": "url - Information about reversing a string.",
"TEXT_REVERSE_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].",
"LISTS_CREATE_EMPTY_HELPURL": "url - Information on empty lists.",
"LISTS_CREATE_EMPTY_TITLE": "block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list].",
"LISTS_CREATE_EMPTY_TOOLTIP": "block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list].",

View File

@@ -766,6 +766,30 @@ Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.';
/// https://github.com/google/blockly/wiki/Text#printing-text].
Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.';
/// block text - Title of a block that counts the number of instances of
/// a smaller pattern (%1) inside a longer string (%2).
Blockly.Msg.TEXT_COUNT_MESSAGE0 = 'count %1 in %2';
/// url - Information about counting how many times a string appears in another string.
Blockly.Msg.TEXT_COUNT_HELPURL = 'https://github.com/google/blockly/wiki/Text#counting-substrings';
/// tooltip - Short description of a block that counts how many times some text occurs within some other text.
Blockly.Msg.TEXT_COUNT_TOOLTIP = 'Count how many times some text occurs within some other text.';
/// block text - Title of a block that returns a copy of text (%3) with all
/// instances of some smaller text (%1) replaced with other text (%2).
Blockly.Msg.TEXT_REPLACE_MESSAGE0 = 'replace %1 with %2 in %3';
/// url - Information about replacing each copy text (or string, in computer lingo) with other text.
Blockly.Msg.TEXT_REPLACE_HELPURL = 'https://github.com/google/blockly/wiki/Text#replacing-substrings';
/// tooltip - Short description of a block that replaces copies of text in a large text with other text.
Blockly.Msg.TEXT_REPLACE_TOOLTIP = 'Replace all occurances of some text within some other text.';
/// block text - Title of block that returns a copy of text (%1) with the order
/// of letters and characters reversed.
Blockly.Msg.TEXT_REVERSE_MESSAGE0 = 'reverse %1';
/// url - Information about reversing a letters/characters in text.
Blockly.Msg.TEXT_REVERSE_HELPURL = 'https://github.com/google/blockly/wiki/Text#reversing-text';
/// tooltip - See [https://github.com/google/blockly/wiki/Text].
Blockly.Msg.TEXT_REVERSE_TOOLTIP = 'Reverses the order of the characters in the text.';
// Lists Blocks.
/// url - Information on empty lists.
Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-empty-list';

View File

@@ -280,6 +280,9 @@ h1 {
<block type="text_trim"></block>
<block type="text_print"></block>
<block type="text_prompt_ext"></block>
<block type="text_count"></block>
<block type="text_replace"></block>
<block type="text_reverse"></block>
</category>
<category name="Lists" colour="260">
<block type="lists_create_empty"></block>

View File

@@ -1,5 +1,5 @@
<xml xmlns="http://www.w3.org/1999/xhtml">
<block type="unittest_main" x="13" y="13">
<block type="unittest_main" x="13" y="-63">
<statement name="DO">
<block type="procedures_callnoreturn">
<mutation name="test length"></mutation>
@@ -36,6 +36,21 @@
<next>
<block type="procedures_callnoreturn">
<mutation name="test trim"></mutation>
<next>
<block type="procedures_callnoreturn">
<mutation name="test count"></mutation>
<next>
<block type="procedures_callnoreturn">
<mutation name="test reverse"></mutation>
<next>
<block type="procedures_callnoreturn">
<mutation name="test replace"></mutation>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
@@ -4091,4 +4106,545 @@
</block>
</statement>
</block>
<block type="procedures_defnoreturn" x="13" y="12088">
<field name="NAME">test count</field>
<comment pinned="false" h="80" w="160">Tests the "trim" block.</comment>
<statement name="STACK">
<block type="variables_set">
<field name="VAR">text</field>
<value name="VALUE">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">len 1</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT">o</field>
</block>
</value>
<value name="TEXT">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">8</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">len 2</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT">oo</field>
</block>
</value>
<value name="TEXT">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">4</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">len 3</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT">loo</field>
</block>
</value>
<value name="TEXT">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">2</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">start</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT">wool</field>
</block>
</value>
<value name="TEXT">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">1</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">missing</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT">chicken</field>
</block>
</value>
<value name="TEXT">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">0</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty needle</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<value name="TEXT">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">14</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty source</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_count">
<value name="SUB">
<block type="text">
<field name="TEXT">chicken</field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="math_number">
<field name="NUM">0</field>
</block>
</value>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</statement>
</block>
<block type="procedures_defnoreturn" x="12" y="12812">
<field name="NAME">test reverse</field>
<comment pinned="false" h="80" w="160">Tests the "trim" block.</comment>
<statement name="STACK">
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty string</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_reverse">
<value name="TEXT">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">len 1</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_reverse">
<value name="TEXT">
<block type="text">
<field name="TEXT">a</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">a</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">len 2</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_reverse">
<value name="TEXT">
<block type="text">
<field name="TEXT">ab</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">ba</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">longer</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_reverse">
<value name="TEXT">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">ooloomoolloow</field>
</block>
</value>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</statement>
</block>
<block type="procedures_defnoreturn" x="12" y="13237">
<field name="NAME">test replace</field>
<comment pinned="false" h="80" w="160">Tests the "trim" block.</comment>
<statement name="STACK">
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">replace all instances 1</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">oo</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT">123</field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">w123ll123m123l123</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">literal string replacement</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">.oo</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT">X</field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">not found</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">abc</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT">X</field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty replacement 1</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">o</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT">woolloomooloo</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT">wllml</field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty replacement 2</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">aaaaa</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT">aaaaa</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty replacement 3</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">a</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT">aaaaa</field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
<next>
<block type="unittest_assertequals" inline="false">
<value name="MESSAGE">
<block type="text">
<field name="TEXT">empty source</field>
</block>
</value>
<value name="ACTUAL">
<block type="text_replace">
<value name="FROM">
<block type="text">
<field name="TEXT">a</field>
</block>
</value>
<value name="TO">
<block type="text">
<field name="TEXT">chicken</field>
</block>
</value>
<value name="TEXT">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
</block>
</value>
<value name="EXPECTED">
<block type="text">
<field name="TEXT"></field>
</block>
</value>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</next>
</block>
</statement>
</block>
</xml>

View File

@@ -591,6 +591,30 @@ h1 {
</shadow>
</value>
</block>
<block type="text_count">
<value name="SUB">
<shadow type="text"></shadow>
</value>
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_replace">
<value name="FROM">
<shadow type="text"></shadow>
</value>
<value name="TO">
<shadow type="text"></shadow>
</value>
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_reverse">
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<label text="Input/Output:" web-class="ioLabel"></label>
<block type="text_print">
<value name="TEXT">