chore: Use ES6 template strings in CSS and code generators (#5902)

* Unindent CSS, save 3 kb of code.
* Convert generator functions to template strings. 
This resolves #5761.
This commit is contained in:
Neil Fraser
2022-01-28 17:58:43 -08:00
committed by GitHub
parent a31003fab9
commit 1f6a1bd8d9
39 changed files with 2194 additions and 2062 deletions

View File

@@ -29,13 +29,13 @@ Python['colour_random'] = function(block) {
Python['colour_rgb'] = function(block) {
// Compose a colour from RGB components expressed as percentages.
const functionName = Python.provideFunction_('colour_rgb', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):',
' r = round(min(100, max(0, r)) * 2.55)',
' g = round(min(100, max(0, g)) * 2.55)',
' b = round(min(100, max(0, b)) * 2.55)',
' return \'#%02x%02x%02x\' % (r, g, b)'
]);
const functionName = Python.provideFunction_('colour_rgb', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(r, g, b):
r = round(min(100, max(0, r)) * 2.55)
g = round(min(100, max(0, g)) * 2.55)
b = round(min(100, max(0, b)) * 2.55)
return \'#%02x%02x%02x\' % (r, g, b)
`);
const r = Python.valueToCode(block, 'RED', Python.ORDER_NONE) || 0;
const g = Python.valueToCode(block, 'GREEN', Python.ORDER_NONE) || 0;
const b = Python.valueToCode(block, 'BLUE', Python.ORDER_NONE) || 0;
@@ -45,17 +45,17 @@ Python['colour_rgb'] = function(block) {
Python['colour_blend'] = function(block) {
// Blend two colours together.
const functionName = Python.provideFunction_('colour_blend', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(colour1, colour2, ratio):',
' r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)',
' g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)',
' b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)',
' ratio = min(1, max(0, ratio))',
' r = round(r1 * (1 - ratio) + r2 * ratio)',
' g = round(g1 * (1 - ratio) + g2 * ratio)',
' b = round(b1 * (1 - ratio) + b2 * ratio)',
' return \'#%02x%02x%02x\' % (r, g, b)'
]);
const functionName = Python.provideFunction_('colour_blend', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(colour1, colour2, ratio):
r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)
g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)
b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)
ratio = min(1, max(0, ratio))
r = round(r1 * (1 - ratio) + r2 * ratio)
g = round(g1 * (1 - ratio) + g2 * ratio)
b = round(b1 * (1 - ratio) + b2 * ratio)
return \'#%02x%02x%02x\' % (r, g, b)
`);
const colour1 =
Python.valueToCode(block, 'COLOUR1', Python.ORDER_NONE) || '\'#000000\'';
const colour2 =

View File

@@ -57,7 +57,7 @@ Python['lists_isEmpty'] = function(block) {
Python['lists_indexOf'] = function(block) {
// Find an item in the list.
const item = Python.valueToCode(block, 'FIND', Python.ORDER_NONE) || '[]';
const list = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '\'\'';
const list = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || "''";
let errorIndex = ' -1';
let firstIndexAdjustment = '';
let lastIndexAdjustment = ' - 1';
@@ -68,21 +68,22 @@ Python['lists_indexOf'] = function(block) {
lastIndexAdjustment = '';
}
let functionName;
if (block.getFieldValue('END') === 'FIRST') {
const functionName = Python.provideFunction_('first_index', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(my_list, elem):',
' try: index = my_list.index(elem)' + firstIndexAdjustment,
' except: index =' + errorIndex, ' return index'
]);
const code = functionName + '(' + list + ', ' + item + ')';
return [code, Python.ORDER_FUNCTION_CALL];
functionName = Python.provideFunction_('first_index', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(my_list, elem):
try: index = my_list.index(elem)${firstIndexAdjustment}
except: index =${errorIndex}
return index
`);
} else {
functionName = Python.provideFunction_('last_index', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(my_list, elem):
try: index = len(my_list) - my_list[::-1].index(elem)${lastIndexAdjustment}
except: index =${errorIndex}
return index
`);
}
const functionName = Python.provideFunction_('last_index', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(my_list, elem):',
' try: index = len(my_list) - my_list[::-1].index(elem)' +
lastIndexAdjustment,
' except: index =' + errorIndex, ' return index'
]);
const code = functionName + '(' + list + ', ' + item + ')';
return [code, Python.ORDER_FUNCTION_CALL];
};
@@ -152,11 +153,11 @@ Python['lists_getIndex'] = function(block) {
return [code, Python.ORDER_FUNCTION_CALL];
} else {
const functionName =
Python.provideFunction_('lists_remove_random_item', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',
' x = int(random.random() * len(myList))',
' return myList.pop(x)'
]);
Python.provideFunction_('lists_remove_random_item', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(myList):
x = int(random.random() * len(myList))
return myList.pop(x)
`);
const code = functionName + '(' + list + ')';
if (mode === 'GET_REMOVE') {
return [code, Python.ORDER_FUNCTION_CALL];
@@ -294,15 +295,22 @@ Python['lists_sort'] = function(block) {
const list = (Python.valueToCode(block, 'LIST', Python.ORDER_NONE) || '[]');
const type = block.getFieldValue('TYPE');
const reverse = block.getFieldValue('DIRECTION') === '1' ? 'False' : 'True';
const sortFunctionName = Python.provideFunction_('lists_sort', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(my_list, type, reverse):',
' def try_float(s):', ' try:', ' return float(s)', ' except:',
' return 0', ' key_funcs = {', ' "NUMERIC": try_float,',
' "TEXT": str,', ' "IGNORE_CASE": lambda s: str(s).lower()', ' }',
' key_func = key_funcs[type]',
' list_cpy = list(my_list)', // Clone the list.
' return sorted(list_cpy, key=key_func, reverse=reverse)'
]);
const sortFunctionName = Python.provideFunction_('lists_sort', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(my_list, type, reverse):
def try_float(s):
try:
return float(s)
except:
return 0
key_funcs = {
"NUMERIC": try_float,
"TEXT": str,
"IGNORE_CASE": lambda s: str(s).lower()
}
key_func = key_funcs[type]
list_cpy = list(my_list)
return sorted(list_cpy, key=key_func, reverse=reverse)
`);
const code =
sortFunctionName + '(' + list + ', "' + type + '", ' + reverse + ')';
@@ -315,14 +323,14 @@ Python['lists_split'] = function(block) {
let code;
if (mode === 'SPLIT') {
const value_input =
Python.valueToCode(block, 'INPUT', Python.ORDER_MEMBER) || '\'\'';
Python.valueToCode(block, 'INPUT', Python.ORDER_MEMBER) || "''";
const value_delim = Python.valueToCode(block, 'DELIM', Python.ORDER_NONE);
code = value_input + '.split(' + value_delim + ')';
} else if (mode === 'JOIN') {
const value_input =
Python.valueToCode(block, 'INPUT', Python.ORDER_NONE) || '[]';
const value_delim =
Python.valueToCode(block, 'DELIM', Python.ORDER_MEMBER) || '\'\'';
Python.valueToCode(block, 'DELIM', Python.ORDER_MEMBER) || "''";
code = value_delim + '.join(' + value_input + ')';
} else {
throw Error('Unknown mode: ' + mode);

View File

@@ -70,16 +70,20 @@ Python['controls_for'] = function(block) {
// Helper functions.
const defineUpRange = function() {
return Python.provideFunction_('upRange', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(start, stop, step):',
' while start <= stop:', ' yield start', ' start += abs(step)'
]);
return Python.provideFunction_('upRange', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(start, stop, step):
while start <= stop:
yield start
start += abs(step)
`);
};
const defineDownRange = function() {
return Python.provideFunction_('downRange', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(start, stop, step):',
' while start >= stop:', ' yield start', ' start -= abs(step)'
]);
return Python.provideFunction_('downRange', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(start, stop, step):
while start >= stop:
yield start
start -= abs(step)
`);
};
// Arguments are legal Python code (numbers or strings returned by scrub()).
const generateUpDownRange = function(start, end, inc) {

View File

@@ -41,7 +41,7 @@ Python['math_arithmetic'] = function(block) {
'MINUS': [' - ', Python.ORDER_ADDITIVE],
'MULTIPLY': [' * ', Python.ORDER_MULTIPLICATIVE],
'DIVIDE': [' / ', Python.ORDER_MULTIPLICATIVE],
'POWER': [' ** ', Python.ORDER_EXPONENTIATION]
'POWER': [' ** ', Python.ORDER_EXPONENTIATION],
};
const tuple = OPERATORS[block.getFieldValue('OP')];
const operator = tuple[0];
@@ -142,7 +142,7 @@ Python['math_constant'] = function(block) {
'GOLDEN_RATIO': ['(1 + math.sqrt(5)) / 2', Python.ORDER_MULTIPLICATIVE],
'SQRT2': ['math.sqrt(2)', Python.ORDER_MEMBER],
'SQRT1_2': ['math.sqrt(1.0 / 2)', Python.ORDER_MEMBER],
'INFINITY': ['float(\'inf\')', Python.ORDER_ATOMIC]
'INFINITY': ['float(\'inf\')', Python.ORDER_ATOMIC],
};
const constant = block.getFieldValue('CONSTANT');
if (constant !== 'INFINITY') {
@@ -155,20 +155,15 @@ Python['math_number_property'] = function(block) {
// Check if a number is even, odd, prime, whole, positive, or negative
// or if it is divisible by certain number. Returns true or false.
const PROPERTIES = {
'EVEN': [' % 2 == 0', Python.ORDER_MULTIPLICATIVE,
Python.ORDER_RELATIONAL],
'ODD': [' % 2 == 1', Python.ORDER_MULTIPLICATIVE,
Python.ORDER_RELATIONAL],
'EVEN': [' % 2 == 0', Python.ORDER_MULTIPLICATIVE, Python.ORDER_RELATIONAL],
'ODD': [' % 2 == 1', Python.ORDER_MULTIPLICATIVE, Python.ORDER_RELATIONAL],
'WHOLE': [' % 1 == 0', Python.ORDER_MULTIPLICATIVE,
Python.ORDER_RELATIONAL],
'POSITIVE': [' > 0', Python.ORDER_RELATIONAL,
Python.ORDER_RELATIONAL],
'NEGATIVE': [' < 0', Python.ORDER_RELATIONAL,
Python.ORDER_RELATIONAL],
'POSITIVE': [' > 0', Python.ORDER_RELATIONAL, Python.ORDER_RELATIONAL],
'NEGATIVE': [' < 0', Python.ORDER_RELATIONAL, Python.ORDER_RELATIONAL],
'DIVISIBLE_BY': [null, Python.ORDER_MULTIPLICATIVE,
Python.ORDER_RELATIONAL],
'PRIME': [null, Python.ORDER_NONE,
Python.ORDER_FUNCTION_CALL]
'PRIME': [null, Python.ORDER_NONE, Python.ORDER_FUNCTION_CALL],
}
const dropdownProperty = block.getFieldValue('PROPERTY');
const [suffix, inputOrder, outputOrder] = PROPERTIES[dropdownProperty];
@@ -180,27 +175,26 @@ Python['math_number_property'] = function(block) {
Python.definitions_['import_math'] = 'import math';
Python.definitions_['from_numbers_import_Number'] =
'from numbers import Number';
const functionName = Python.provideFunction_(
'math_isPrime',
['def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(n):',
' # https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
' # If n is not a number but a string, try parsing it.',
' if not isinstance(n, Number):',
' try:',
' n = float(n)',
' except:',
' return False',
' if n == 2 or n == 3:',
' return True',
' # False if n is negative, is 1, or not whole,' +
' or if n is divisible by 2 or 3.',
' if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:',
' return False',
' # Check all the numbers of form 6k +/- 1, up to sqrt(n).',
' for x in range(6, int(math.sqrt(n)) + 2, 6):',
' if n % (x - 1) == 0 or n % (x + 1) == 0:',
' return False',
' return True']);
const functionName = Python.provideFunction_('math_isPrime', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(n):
# https://en.wikipedia.org/wiki/Primality_test#Naive_methods
# If n is not a number but a string, try parsing it.
if not isinstance(n, Number):
try:
n = float(n)
except:
return False
if n == 2 or n == 3:
return True
# False if n is negative, is 1, or not whole, or if n is divisible by 2 or 3.
if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:
return False
# Check all the numbers of form 6k +/- 1, up to sqrt(n).
for x in range(6, int(math.sqrt(n)) + 2, 6):
if n % (x - 1) == 0 or n % (x + 1) == 0:
return False
return True
`);
code = functionName + '(' + numberToCheck + ')';
} else if (dropdownProperty === 'DIVISIBLE_BY') {
const divisor = Python.valueToCode(block, 'DIVISOR',
@@ -251,71 +245,72 @@ Python['math_on_list'] = function(block) {
case 'AVERAGE': {
Python.definitions_['from_numbers_import_Number'] =
'from numbers import Number';
const functionName = Python.provideFunction_(
'math_mean',
// This operation excludes null and values that aren't int or float:
// math_mean([null, null, "aString", 1, 9]) -> 5.0
[
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',
' localList = [e for e in myList if isinstance(e, Number)]',
' if not localList: return',
' return float(sum(localList)) / len(localList)'
]);
// This operation excludes null and values that aren't int or float:
// math_mean([null, null, "aString", 1, 9]) -> 5.0
const functionName = Python.provideFunction_('math_mean', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(myList):
localList = [e for e in myList if isinstance(e, Number)]
if not localList: return
return float(sum(localList)) / len(localList)
`);
code = functionName + '(' + list + ')';
break;
}
case 'MEDIAN': {
Python.definitions_['from_numbers_import_Number'] =
'from numbers import Number';
const functionName = Python.provideFunction_(
'math_median',
// This operation excludes null values:
// math_median([null, null, 1, 3]) -> 2.0
[
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',
' localList = sorted([e for e in myList if isinstance(e, Number)])',
' if not localList: return', ' if len(localList) % 2 == 0:',
' return (localList[len(localList) // 2 - 1] + ' +
'localList[len(localList) // 2]) / 2.0',
' else:', ' return localList[(len(localList) - 1) // 2]'
]);
// This operation excludes null values:
// math_median([null, null, 1, 3]) -> 2.0
const functionName = Python.provideFunction_( 'math_median', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(myList):
localList = sorted([e for e in myList if isinstance(e, Number)])
if not localList: return
if len(localList) % 2 == 0:
return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0
else:
return localList[(len(localList) - 1) // 2]
`);
code = functionName + '(' + list + ')';
break;
}
case 'MODE': {
const functionName = Python.provideFunction_(
'math_modes',
// As a list of numbers can contain more than one mode,
// the returned result is provided as an array.
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]
[
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(some_list):',
' modes = []',
' # Using a lists of [item, count] to keep count rather than dict',
' # to avoid "unhashable" errors when the counted item is ' +
'itself a list or dict.',
' counts = []', ' maxCount = 1', ' for item in some_list:',
' found = False', ' for count in counts:',
' if count[0] == item:', ' count[1] += 1',
' maxCount = max(maxCount, count[1])',
' found = True',
' if not found:', ' counts.append([item, 1])',
' for counted_item, item_count in counts:',
' if item_count == maxCount:',
' modes.append(counted_item)', ' return modes'
]);
// As a list of numbers can contain more than one mode,
// the returned result is provided as an array.
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]
const functionName = Python.provideFunction_('math_modes', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(some_list):
modes = []
# Using a lists of [item, count] to keep count rather than dict
# to avoid "unhashable" errors when the counted item is itself a list or dict.
counts = []
maxCount = 1
for item in some_list:
found = False
for count in counts:
if count[0] == item:
count[1] += 1
maxCount = max(maxCount, count[1])
found = True
if not found:
counts.append([item, 1])
for counted_item, item_count in counts:
if item_count == maxCount:
modes.append(counted_item)
return modes
`);
code = functionName + '(' + list + ')';
break;
}
case 'STD_DEV': {
Python.definitions_['import_math'] = 'import math';
const functionName = Python.provideFunction_('math_standard_deviation', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(numbers):',
' n = len(numbers)', ' if n == 0: return',
' mean = float(sum(numbers)) / n',
' variance = sum((x - mean) ** 2 for x in numbers) / n',
' return math.sqrt(variance)'
]);
const functionName = Python.provideFunction_('math_standard_deviation', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(numbers):
n = len(numbers)
if n == 0: return
mean = float(sum(numbers)) / n
variance = sum((x - mean) ** 2 for x in numbers) / n
return math.sqrt(variance)
`);
code = functionName + '(' + list + ')';
break;
}

View File

@@ -55,18 +55,18 @@ Python['text_join'] = function(block) {
// Should we allow joining by '-' or ',' or any other characters?
switch (block.itemCount_) {
case 0:
return ['\'\'', Python.ORDER_ATOMIC];
return ["''", Python.ORDER_ATOMIC];
case 1: {
const element =
Python.valueToCode(block, 'ADD0', Python.ORDER_NONE) || '\'\'';
Python.valueToCode(block, 'ADD0', Python.ORDER_NONE) || "''";
const codeAndOrder = forceString(element);
return codeAndOrder;
}
case 2: {
const element0 =
Python.valueToCode(block, 'ADD0', Python.ORDER_NONE) || '\'\'';
Python.valueToCode(block, 'ADD0', Python.ORDER_NONE) || "''";
const element1 =
Python.valueToCode(block, 'ADD1', Python.ORDER_NONE) || '\'\'';
Python.valueToCode(block, 'ADD1', Python.ORDER_NONE) || "''";
const code = forceString(element0)[0] + ' + ' + forceString(element1)[0];
return [code, Python.ORDER_ADDITIVE];
}
@@ -74,7 +74,7 @@ Python['text_join'] = function(block) {
const elements = [];
for (let i = 0; i < block.itemCount_; i++) {
elements[i] =
Python.valueToCode(block, 'ADD' + i, Python.ORDER_NONE) || '\'\'';
Python.valueToCode(block, 'ADD' + i, Python.ORDER_NONE) || "''";
}
const tempVar = Python.nameDB_.getDistinctName('x', NameType.VARIABLE);
const code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' +
@@ -88,19 +88,19 @@ Python['text_append'] = function(block) {
// Append to a variable in place.
const varName =
Python.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE);
const value = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || '\'\'';
const value = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || "''";
return varName + ' = str(' + varName + ') + ' + forceString(value)[0] + '\n';
};
Python['text_length'] = function(block) {
// Is the string null or array empty?
const text = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '\'\'';
const text = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || "''";
return ['len(' + text + ')', Python.ORDER_FUNCTION_CALL];
};
Python['text_isEmpty'] = function(block) {
// Is the string null or array empty?
const text = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || '\'\'';
const text = Python.valueToCode(block, 'VALUE', Python.ORDER_NONE) || "''";
const code = 'not len(' + text + ')';
return [code, Python.ORDER_LOGICAL_NOT];
};
@@ -110,9 +110,9 @@ Python['text_indexOf'] = function(block) {
// Should we allow for non-case sensitive???
const operator = block.getFieldValue('END') === 'FIRST' ? 'find' : 'rfind';
const substring =
Python.valueToCode(block, 'FIND', Python.ORDER_NONE) || '\'\'';
Python.valueToCode(block, 'FIND', Python.ORDER_NONE) || "''";
const text =
Python.valueToCode(block, 'VALUE', Python.ORDER_MEMBER) || '\'\'';
Python.valueToCode(block, 'VALUE', Python.ORDER_MEMBER) || "''";
const code = text + '.' + operator + '(' + substring + ')';
if (block.workspace.options.oneBasedIndex) {
return [code + ' + 1', Python.ORDER_ADDITIVE];
@@ -126,7 +126,7 @@ Python['text_charAt'] = function(block) {
const where = block.getFieldValue('WHERE') || 'FROM_START';
const textOrder =
(where === 'RANDOM') ? Python.ORDER_NONE : Python.ORDER_MEMBER;
const text = Python.valueToCode(block, 'VALUE', textOrder) || '\'\'';
const text = Python.valueToCode(block, 'VALUE', textOrder) || "''";
switch (where) {
case 'FIRST': {
const code = text + '[0]';
@@ -148,10 +148,11 @@ Python['text_charAt'] = function(block) {
}
case 'RANDOM': {
Python.definitions_['import_random'] = 'import random';
const functionName = Python.provideFunction_('text_random_letter', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(text):',
' x = int(random.random() * len(text))', ' return text[x];'
]);
const functionName = Python.provideFunction_('text_random_letter', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(text):
x = int(random.random() * len(text))
return text[x]
`);
const code = functionName + '(' + text + ')';
return [code, Python.ORDER_FUNCTION_CALL];
}
@@ -164,7 +165,7 @@ Python['text_getSubstring'] = function(block) {
const where1 = block.getFieldValue('WHERE1');
const where2 = block.getFieldValue('WHERE2');
const text =
Python.valueToCode(block, 'STRING', Python.ORDER_MEMBER) || '\'\'';
Python.valueToCode(block, 'STRING', Python.ORDER_MEMBER) || "''";
let at1;
switch (where1) {
case 'FROM_START':
@@ -217,7 +218,7 @@ Python['text_changeCase'] = function(block) {
'TITLECASE': '.title()'
};
const operator = OPERATORS[block.getFieldValue('CASE')];
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || '\'\'';
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || "''";
const code = text + operator;
return [code, Python.ORDER_FUNCTION_CALL];
};
@@ -230,30 +231,33 @@ Python['text_trim'] = function(block) {
'BOTH': '.strip()'
};
const operator = OPERATORS[block.getFieldValue('MODE')];
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || '\'\'';
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || "''";
const code = text + operator;
return [code, Python.ORDER_FUNCTION_CALL];
};
Python['text_print'] = function(block) {
// Print statement.
const msg = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || '\'\'';
const msg = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || "''";
return 'print(' + msg + ')\n';
};
Python['text_prompt_ext'] = function(block) {
// Prompt function.
const functionName = Python.provideFunction_('text_prompt', [
'def ' + Python.FUNCTION_NAME_PLACEHOLDER_ + '(msg):', ' try:',
' return raw_input(msg)', ' except NameError:', ' return input(msg)'
]);
const functionName = Python.provideFunction_('text_prompt', `
def ${Python.FUNCTION_NAME_PLACEHOLDER_}(msg):
try:
return raw_input(msg)
except NameError:
return input(msg)
`);
let msg;
if (block.getField('TEXT')) {
// Internal message.
msg = Python.quote_(block.getFieldValue('TEXT'));
} else {
// External message.
msg = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || '\'\'';
msg = Python.valueToCode(block, 'TEXT', Python.ORDER_NONE) || "''";
}
let code = functionName + '(' + msg + ')';
const toNumber = block.getFieldValue('TYPE') === 'NUMBER';
@@ -266,22 +270,22 @@ Python['text_prompt_ext'] = function(block) {
Python['text_prompt'] = Python['text_prompt_ext'];
Python['text_count'] = function(block) {
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || '\'\'';
const sub = Python.valueToCode(block, 'SUB', Python.ORDER_NONE) || '\'\'';
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || "''";
const sub = Python.valueToCode(block, 'SUB', Python.ORDER_NONE) || "''";
const code = text + '.count(' + sub + ')';
return [code, Python.ORDER_FUNCTION_CALL];
};
Python['text_replace'] = function(block) {
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || '\'\'';
const from = Python.valueToCode(block, 'FROM', Python.ORDER_NONE) || '\'\'';
const to = Python.valueToCode(block, 'TO', Python.ORDER_NONE) || '\'\'';
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || "''";
const from = Python.valueToCode(block, 'FROM', Python.ORDER_NONE) || "''";
const to = Python.valueToCode(block, 'TO', Python.ORDER_NONE) || "''";
const code = text + '.replace(' + from + ', ' + to + ')';
return [code, Python.ORDER_MEMBER];
};
Python['text_reverse'] = function(block) {
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || '\'\'';
const text = Python.valueToCode(block, 'TEXT', Python.ORDER_MEMBER) || "''";
const code = text + '[::-1]';
return [code, Python.ORDER_MEMBER];
};