[Update] Epsilon 14

This commit is contained in:
Joachim LF
2020-07-09 15:33:21 +02:00
committed by Quentin Guidée
320 changed files with 6893 additions and 2610 deletions

View File

@@ -1,10 +1,6 @@
apps += Code::App
app_headers += apps/code/app.h
app_code_test_src = $(addprefix apps/code/,\
script_template.cpp \
)
app_code_src = $(addprefix apps/code/,\
app.cpp \
console_controller.cpp \
@@ -15,42 +11,31 @@ app_code_src = $(addprefix apps/code/,\
editor_view.cpp \
helpers.cpp \
menu_controller.cpp \
python_toolbox.cpp \
python_text_area.cpp \
sandbox_controller.cpp \
script.cpp \
script_name_cell.cpp \
script_node_cell.cpp \
script_parameter_controller.cpp \
)
app_code_test_src = $(addprefix apps/code/,\
python_toolbox.cpp \
script.cpp \
script_node_cell.cpp \
script_store.cpp \
script_template.cpp \
variable_box_empty_controller.cpp \
variable_box_controller.cpp \
)
tests_src += $(addprefix apps/code/test/,\
variable_box_controller.cpp\
)
app_code_src += $(app_code_test_src)
apps_src += $(app_code_src)
i18n_files += $(addprefix apps/code/,\
base.de.i18n\
base.en.i18n\
base.es.i18n\
base.fr.i18n\
base.pt.i18n\
base.hu.i18n\
base.universal.i18n\
catalog.de.i18n\
catalog.en.i18n\
catalog.es.i18n\
catalog.fr.i18n\
catalog.pt.i18n\
catalog.hu.i18n\
catalog.universal.i18n\
toolbox.de.i18n\
toolbox.en.i18n\
toolbox.es.i18n\
toolbox.fr.i18n\
toolbox.pt.i18n\
toolbox.hu.i18n\
toolbox.universal.i18n\
)
i18n_files += $(call i18n_with_universal_for,code/base)
i18n_files += $(call i18n_with_universal_for,code/catalog)
i18n_files += $(call i18n_with_universal_for,code/toolbox)
$(eval $(call depends_on_image,apps/code/app.cpp,apps/code/code_icon.png))

View File

@@ -67,7 +67,7 @@ void App::Snapshot::setOpt(const char * name, const char * value) {
const char * scriptContent = separator;
Code::ScriptTemplate script(scriptName, scriptContent);
m_scriptStore.addScriptFromTemplate(&script);
m_scriptStore.scriptNamed(scriptName).toggleImportationStatus(); // set Importation Status to 1
ScriptStore::ScriptNamed(scriptName).toggleAutoimportationStatus(); // set Importation Status to 1
return;
}
if (strcmp(name, "lock-on-console") == 0) {

View File

@@ -51,6 +51,7 @@ public:
}
StackViewController * stackViewController() { return &m_codeStackViewController; }
ConsoleController * consoleController() { return &m_consoleController; }
MenuController * menuController() { return &m_menuController; }
/* Responder */
bool handleEvent(Ion::Events::Event event) override;

View File

@@ -1,10 +1,15 @@
Console = "Interaktive Konsole"
AddScript = "Skript hinzufügen"
ScriptOptions = "Skriptoptionen"
ExecuteScript = "Skript ausführen"
AllowedCharactersaz09 = "Erlaubte Zeichen: a-z, 0-9, _"
Autocomplete = "Autovervollständigung"
AutoImportScript = "Automatischer Import in Konsole"
BuiltinsAndKeywords = "Native Funktionen und Schlüsselwörter"
Console = "Interaktive Konsole"
DeleteScript = "Skript löschen"
DuplicateScript = "Skript duplizieren"
ExecuteScript = "Skript ausführen"
FunctionsAndVariables = "Funktionen und Variablen"
AllowedCharactersaz09 = "Erlaubte Zeichen: a-z, 0-9, _"
ScriptSize = "Skriptgrösse"
ImportedModulesAndScripts = "Importierte Module und Skripte"
NoWordAvailableHere = "Kein Wort ist hier verfübar."
ScriptInProgress = "Aktuelle Skript"
ScriptOptions = "Skriptoptionen"
ScriptSize = "Script size"

View File

@@ -1,10 +1,15 @@
Console = "Python shell"
AddScript = "Add a script"
ScriptOptions = "Script options"
ExecuteScript = "Execute script"
AllowedCharactersaz09 = "Allowed characters: a-z, 0-9, _"
Autocomplete = "Autocomplete"
AutoImportScript = "Auto import in shell"
BuiltinsAndKeywords = "Builtins and keywords"
Console = "Python shell"
DeleteScript = "Delete script"
DuplicateScript = "Duplicate script"
ExecuteScript = "Execute script"
FunctionsAndVariables = "Functions and variables"
AllowedCharactersaz09 = "Allowed characters: a-z, 0-9, _"
ImportedModulesAndScripts = "Imported modules and scripts"
NoWordAvailableHere = "No word available here."
ScriptInProgress = "Script in progress"
ScriptOptions = "Script options"
ScriptSize = "Script size"

View File

@@ -1,10 +1,15 @@
Console = "Interprete de comandos"
AddScript = "Agregar un archivo"
ScriptOptions = "Opciones del archivo"
ExecuteScript = "Ejecutar el archivo"
AllowedCharactersaz09 = "Caracteres permitidos : a-z, 0-9, _"
Autocomplete = "Autocompleción"
AutoImportScript = "Importación auto en intérprete"
BuiltinsAndKeywords = "Funciones nativas y palabras clave"
Console = "Interprete de comandos"
DeleteScript = "Eliminar el archivo"
DuplicateScript = "Duplicar el guión"
ExecuteScript = "Ejecutar el archivo"
FunctionsAndVariables = "Funciones y variables"
AllowedCharactersaz09 = "Caracteres permitidos : a-z, 0-9, _"
ScriptSize = "tamano del script"
ImportedModulesAndScripts = "Módulos y archivos importados"
NoWordAvailableHere = "No hay ninguna palabra disponible aquí."
ScriptInProgress = "Archivo en curso"
ScriptOptions = "Opciones del archivo"
ScriptSize = "Script size"

View File

@@ -1,10 +1,15 @@
Console = "Console d'exécution"
AddScript = "Ajouter un script"
ScriptOptions = "Options de script"
ExecuteScript = "Exécuter le script"
AllowedCharactersaz09 = "Caractères autorisés : a-z, 0-9, _"
Autocomplete = "Auto-complétion"
AutoImportScript = "Importation auto dans la console"
BuiltinsAndKeywords = "Fonctions natives et mots-clés"
Console = "Console d'exécution"
DeleteScript = "Supprimer le script"
DuplicateScript = "Dupliquer le script"
ExecuteScript = "Exécuter le script"
FunctionsAndVariables = "Fonctions et variables"
AllowedCharactersaz09 = "Caractères autorisés : a-z, 0-9, _"
ScriptSize = "Taille du script"
ImportedModulesAndScripts = "Modules et scripts importés"
NoWordAvailableHere = "Aucun mot disponible à cet endroit."
ScriptInProgress = "Script en cours"
ScriptOptions = "Options de script"
ScriptSize = "Script size"

13
apps/code/base.it.i18n Normal file
View File

@@ -0,0 +1,13 @@
AddScript = "Aggiungere script"
AllowedCharactersaz09 = "Caratteri consentiti : a-z, 0-9, _"
Autocomplete = "Autocompletamento"
AutoImportScript = "Importazione automatica dello script"
BuiltinsAndKeywords = "Funzioni native e parole chiave"
Console = "Console d'esecuzione"
DeleteScript = "Eliminare lo script"
ExecuteScript = "Eseguire lo script"
FunctionsAndVariables = "Funzioni e variabili"
ImportedModulesAndScripts = "Moduli e scripts importati"
NoWordAvailableHere = "Nessuna parola disponibile qui."
ScriptInProgress = "Script in corso"
ScriptOptions = "Opzioni dello script"

13
apps/code/base.nl.i18n Normal file
View File

@@ -0,0 +1,13 @@
AddScript = "Script toevoegen"
AllowedCharactersaz09 = "Toegestane tekens: a-z, 0-9, _"
Autocomplete = "Autocomplete"
AutoImportScript = "Automatisch importeren in shell"
BuiltinsAndKeywords = "Builtins and keywords"
Console = "Python shell"
DeleteScript = "Script verwijderen"
ExecuteScript = "Script uitvoeren"
FunctionsAndVariables = "Functies en variabelen"
ImportedModulesAndScripts = "Imported modules and scripts"
NoWordAvailableHere = "No word available here."
ScriptInProgress = "Script in progress"
ScriptOptions = "Script opties"

View File

@@ -1,10 +1,14 @@
Console = "Interpretador interativo"
AddScript = "Adicionar um script"
ScriptOptions = "Opções de script"
ExecuteScript = "Executar o script"
AllowedCharactersaz09 = "Caracteres permitidos : a-z, 0-9, _"
Autocomplete = "Preenchimento automático"
AutoImportScript = "Importação auto no interpretador"
BuiltinsAndKeywords = "Funções nativas e palavras-chave"
Console = "Interpretador interativo"
DeleteScript = "Eliminar o script"
DuplicateScript = "Duplicar o script"
ExecuteScript = "Executar o script"
FunctionsAndVariables = "Funções e variáveis"
AllowedCharactersaz09 = "Caracteres permitidos : a-z, 0-9, _"
ScriptSize = "tamanho do script"
ImportedModulesAndScripts = "Módulos e scripts importados"
NoWordAvailableHere = "Nenhuma palavra disponível aqui."
ScriptInProgress = "Script em curso"
ScriptOptions = "Opções de script"

View File

@@ -26,7 +26,18 @@ PythonCeil = "Aufrundung"
PythonChoice = "Zufallszahl aus der Liste"
PythonClear = "Leere die Liste"
PythonCmathFunction = "cmath-Modul-Funktionspräfix"
PythonColor = "Definiert eine RGB-Farbe"
PythonColor = "Definiere eine RGB-Farbe"
PythonColorBlack = "Black color"
PythonColorBlue = "Blue color"
PythonColorBrown = "Brown color"
PythonColorGreen = "Green color"
PythonColorGrey = "Grey color"
PythonColorOrange = "Orange color"
PythonColorPink = "Pink color"
PythonColorPurple = "Purple color"
PythonColorRed = "Red color"
PythonColorWhite = "White color"
PythonColorYellow = "Yellow color"
PythonComplex = "a+ib zurückgeben"
PythonCopySign = "x mit dem Vorzeichen von y"
PythonCos = "Kosinus"
@@ -45,10 +56,10 @@ PythonFillRect = "Malt ein Rechteck bei Pixel (x,y)"
PythonFloat = "Wandelt x zu float um"
PythonFloor = "Floor"
PythonFmod = "a modulo b"
PythonFrExp = "Rest und Exponent von x"
PythonGamma = "Gammafunktion"
PythonGetPixel = "Farbe von Pixel (x,y)"
PythonGetrandbits = "Ganzzahl mit k zufälligen Bits"
PythonFrExp = "Mantissa and exponent of x: (m,e)"
PythonGamma = "Gamma function"
PythonGetPixel = "Return pixel (x,y) color"
PythonGetrandbits = "Integer with k random bits"
PythonGrid = "Toggle the visibility of the grid"
PythonHex = "Ganzzahl zu Hexadecimal"
PythonHist = "Draw the histogram of x"
@@ -162,43 +173,19 @@ PythonText = "Display a text at (x,y) coordinates"
PythonTimeFunction = "time module function prefix"
PythonTrunc = "x truncated to an integer"
PythonTurtleBackward = "Move backward by x pixels"
PythonTurtleBlack = "Schwarze Farbe"
PythonTurtleBlue = "Blaue Farbe"
PythonTurtleBrown = "Braune Farbe"
PythonTurtleCircle = "Circle of radius r pixels"
PythonTurtleColor = "Stiftfarbe setzen"
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
PythonTurtleForward = "Move forward by x pixels"
PythonTurtleFunction = "turtle module function prefix"
PythonTurtleGoto = "Move to (x,y) coordinates"
PythonTurtleGreen = "Grüne Farbe"
PythonTurtleGrey = "Graue Farbe"
PythonTurtleHeading = "Return the current heading"
PythonTurtleHideturtle = "Hide the turtle"
PythonTurtleIsdown = "Return True if the pen is down"
PythonTurtleLeft = "Turn left by a degrees"
PythonTurtleOrange = "Orange color"
PythonTurtlePendown = "Pull the pen down"
PythonTurtlePensize = "Set the line thickness to x pixels"
PythonTurtlePenup = "Pull the pen up"
PythonTurtlePink = "Pinke Farbe"
PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtlePurple = "Purple color"
PythonTurtleRed = "Rote Farbe"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Position des turtles"
PythonTurtleShowturtle = "Die turtle anzeigen"
PythonTurtleSpeed = "Zeichengeschwindigkeit zwischen 0 und 10"
PythonTurtleWhite = "Weiße Farbe"
PythonTurtleYellow = "Gelbe Farbe"
PythonUniform = "Fließkommazahl in [a,b]"
PythonTimeFromImport = "Import time module"
PythonTimeImport = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Warten Sie n Sekunden lang"
PythonTimeMonotonic = "Monotone Zeit zurückgeben"
PythonFileOpen = "Öffnet eine Datei"
PythonFileSeekable = "Ist eine Datei durchsuchbar?"
PythonFileSeek = "Dateicursor verschieben"
@@ -215,3 +202,12 @@ PythonFileName = "Dateiname"
PythonFileMode = "Dateiöffnungsmodus"
PythonFileReadable = "Ist die Datei lesbar?"
PythonFileWritable = "Ist die Datei beschreibbar?"
PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWrite = "Display a text"
PythonUniform = "Floating point number in [a,b]"

View File

@@ -1,7 +1,7 @@
PythonPound = "Comment"
PythonPercent = "Modulo"
Python1J = "Imaginary i"
PythonLF = "Line feed"
PythonLF = "line feed"
PythonTab = "Tabulation"
PythonAmpersand = "Bitwise and"
PythonSymbolExp = "Bitwise exclusive or"
@@ -27,6 +27,17 @@ PythonChoice = "Random number in the list"
PythonClear = "Empty the list"
PythonCmathFunction = "cmath module function prefix"
PythonColor = "Define a rgb color"
PythonColorBlack = "Black color"
PythonColorBlue = "Blue color"
PythonColorBrown = "Brown color"
PythonColorGreen = "Green color"
PythonColorGrey = "Grey color"
PythonColorOrange = "Orange color"
PythonColorPink = "Pink color"
PythonColorPurple = "Purple color"
PythonColorRed = "Red color"
PythonColorWhite = "White color"
PythonColorYellow = "Yellow color"
PythonComplex = "Return a+ib"
PythonCopySign = "Return x with the sign of y"
PythonCos = "Cosine"
@@ -45,7 +56,7 @@ PythonFillRect = "Fill a rectangle at pixel (x,y)"
PythonFloat = "Convert x to a float"
PythonFloor = "Floor"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa and exponent of x"
PythonFrExp = "Mantissa and exponent of x: (m,e)"
PythonGamma = "Gamma function"
PythonGetPixel = "Return pixel (x,y) color"
PythonGetrandbits = "Integer with k random bits"
@@ -162,43 +173,32 @@ PythonText = "Display a text at (x,y) coordinates"
PythonTimeFunction = "time module function prefix"
PythonTrunc = "x truncated to an integer"
PythonTurtleBackward = "Move backward by x pixels"
PythonTurtleBlack = "Black color"
PythonTurtleBlue = "Blue color"
PythonTurtleBrown = "Brown color"
PythonTurtleCircle = "Circle of radius r pixels"
PythonTurtleColor = "Set the pen color"
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
PythonTurtleForward = "Move forward by x pixels"
PythonTurtleFunction = "turtle module function prefix"
PythonTurtleGoto = "Move to (x,y) coordinates"
PythonTurtleGreen = "Green color"
PythonTurtleGrey = "Grey color"
PythonTurtleHeading = "Return the current heading"
PythonTurtleHideturtle = "Hide the turtle"
PythonTurtleIsdown = "Return True if the pen is down"
PythonTurtleLeft = "Turn left by a degrees"
PythonTurtleOrange = "Orange color"
PythonTurtlePendown = "Pull the pen down"
PythonTurtlePensize = "Set the line thickness to x pixels"
PythonTurtlePenup = "Pull the pen up"
PythonTurtlePink = "Pink color"
PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtlePurple = "Purple color"
PythonTurtleRed = "Red color"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWhite = "White color"
PythonTurtleYellow = "Yellow color"
PythonTurtleWrite = "Display a text"
PythonUniform = "Floating point number in [a,b]"
PythonTimeFromImport = "Import time module"
PythonTimeImport = "Import time module"
PythonImportTime = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonTimeMonotonic = "Return monotonic time"
PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"
PythonFileSeek = "Move file's cursor"

View File

@@ -27,6 +27,17 @@ PythonChoice = "Random number in the list"
PythonClear = "Empty the list"
PythonCmathFunction = "cmath module function prefix"
PythonColor = "Define a rgb color"
PythonColorBlack = "Black color"
PythonColorBlue = "Blue color"
PythonColorBrown = "Brown color"
PythonColorGreen = "Green color"
PythonColorGrey = "Grey color"
PythonColorOrange = "Orange color"
PythonColorPink = "Pink color"
PythonColorPurple = "Purple color"
PythonColorRed = "Red color"
PythonColorWhite = "White color"
PythonColorYellow = "Yellow color"
PythonComplex = "Return a+ib"
PythonCopySign = "Return x with the sign of y"
PythonCos = "Cosine"
@@ -45,7 +56,7 @@ PythonFillRect = "Fill a rectangle at pixel (x,y)"
PythonFloat = "Convert x to a float"
PythonFloor = "Floor"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa and exponent of x"
PythonFrExp = "Mantissa and exponent of x: (m,e)"
PythonGamma = "Gamma function"
PythonGetPixel = "Return pixel (x,y) color"
PythonGetrandbits = "Integer with k random bits"
@@ -162,43 +173,32 @@ PythonText = "Display a text at (x,y) coordinates"
PythonTimeFunction = "time module function prefix"
PythonTrunc = "x truncated to an integer"
PythonTurtleBackward = "Move backward by x pixels"
PythonTurtleBlack = "Black color"
PythonTurtleBlue = "Blue color"
PythonTurtleBrown = "Brown color"
PythonTurtleCircle = "Circle of radius r pixels"
PythonTurtleColor = "Set the pen color"
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
PythonTurtleForward = "Move forward by x pixels"
PythonTurtleFunction = "turtle module function prefix"
PythonTurtleGoto = "Move to (x,y) coordinates"
PythonTurtleGreen = "Green color"
PythonTurtleGrey = "Grey color"
PythonTurtleHeading = "Return the current heading"
PythonTurtleHideturtle = "Hide the turtle"
PythonTurtleIsdown = "Return True if the pen is down"
PythonTurtleLeft = "Turn left by a degrees"
PythonTurtleOrange = "Orange color"
PythonTurtlePendown = "Pull the pen down"
PythonTurtlePensize = "Set the line thickness to x pixels"
PythonTurtlePenup = "Pull the pen up"
PythonTurtlePink = "Pink color"
PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtlePurple = "Purple color"
PythonTurtleRed = "Red color"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWhite = "White color"
PythonTurtleYellow = "Yellow color"
PythonTurtleWrite = "Display a text"
PythonUniform = "Floating point number in [a,b]"
PythonTimeFromImport = "Import time module"
PythonTimeImport = "Import time module"
PythonImportTime = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Esperar n segundos"
PythonTimeMonotonic = "Tiempo monótono de retorno"
PythonMonotonic = "Tiempo monótono de retorno"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"
PythonFileSeek = "Move file's internal cursor"

View File

@@ -27,6 +27,17 @@ PythonChoice = "Nombre aléatoire dans la liste"
PythonClear = "Vide la liste"
PythonCmathFunction = "Préfixe fonction du module cmath"
PythonColor = "Définit une couleur rvb"
PythonColorBlack = "Couleur noire"
PythonColorBlue = "Couleur bleue"
PythonColorBrown = "Couleur marron"
PythonColorGreen = "Couleur verte"
PythonColorGrey = "Couleur grise"
PythonColorOrange = "Couleur orange"
PythonColorPink = "Couleur rose"
PythonColorPurple = "Couleur violette"
PythonColorRed = "Couleur rouge"
PythonColorWhite = "Couleur blanche"
PythonColorYellow = "Couleur jaune"
PythonComplex = "Renvoie a+ib"
PythonCopySign = "Renvoie x avec le signe de y"
PythonCos = "Cosinus"
@@ -162,43 +173,32 @@ PythonText = "Affiche un texte en (x,y)"
PythonTimeFunction = "Préfixe fonction module time"
PythonTrunc = "Troncature entière"
PythonTurtleBackward = "Recule de x pixels"
PythonTurtleBlack = "Couleur noire"
PythonTurtleBlue = "Couleur bleue"
PythonTurtleBrown = "Couleur marron"
PythonTurtleCircle = "Cercle de rayon r pixels"
PythonTurtleColor = "Modifie la couleur du tracé"
PythonTurtleColorMode = "Met le mode de couleur à 1.0 ou 255"
PythonTurtleForward = "Avance de x pixels"
PythonTurtleFunction = "Préfixe fonction du module turtle"
PythonTurtleGoto = "Va au point de coordonnées (x,y)"
PythonTurtleGreen = "Couleur verte"
PythonTurtleGrey = "Couleur grise"
PythonTurtleHeading = "Renvoie l'orientation actuelle"
PythonTurtleHideturtle = "Masque la tortue"
PythonTurtleIsdown = "True si le crayon est abaissé"
PythonTurtleLeft = "Pivote de a degrés vers la gauche"
PythonTurtleOrange = "Couleur orange"
PythonTurtlePendown = "Abaisse le crayon"
PythonTurtlePensize = "Taille du tracé en pixels"
PythonTurtlePenup = "Relève le crayon"
PythonTurtlePink = "Couleur rose"
PythonTurtlePosition = "Renvoie la position (x,y)"
PythonTurtlePurple = "Couleur violette"
PythonTurtleRed = "Couleur rouge"
PythonTurtleReset = "Réinitialise le dessin"
PythonTurtleRight = "Pivote de a degrés vers la droite"
PythonTurtleSetheading = "Met un cap de a degrés"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Affiche la tortue"
PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10"
PythonTurtleWhite = "Couleur blanche"
PythonTurtleYellow = "Couleur jaune"
PythonTurtleWrite = "Affiche un texte"
PythonUniform = "Nombre décimal dans [a,b]"
PythonTimeFromImport = "Importation du module temps"
PythonTimeImport = "Importation du module temps"
PythonImportTime = "Importation du module temps"
PythonTimePrefix = "Préfixe fonction du module temps"
PythonTimeSleep = "Attendre n secondes"
PythonTimeMonotonic = "Retourne le temps monotonic"
PythonMonotonic = "Retourne le temps monotonic"
PythonFileOpen = "Ouvre un fichier"
PythonFileSeekable = "Indique si seek peut être utilisé"
PythonFileSeek = "Déplace le curseur interne"

View File

@@ -194,11 +194,10 @@ PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
PythonTurtleWhite = "Fehér szín"
PythonTurtleYellow = "Sárga szín"
PythonUniform = "Lebegöpontos szám [a, b] -ben"
PythonTimeFromImport = "Idömodul importálása"
PythonTimeImport = "Idömodul importálása"
PythonImportTime = "Idömodul importálása"
PythonTimePrefix = "idömodul funkció elötag"
PythonTimeSleep = "Várj n másodpercet"
PythonTimeMonotonic = "Vissza a monoton idö"
PythonMonotonic = "Vissza a monoton idö"
PythonFileOpen = "Fájl megnyitása"
PythonFileSeekable = "A fájl kereshető?"
PythonFileSeek = "A fájl kurzorának áthelyezése"

197
apps/code/catalog.it.i18n Normal file
View File

@@ -0,0 +1,197 @@
PythonPound = "Commento"
PythonPercent = "Modulo"
Python1J = "Unità immaginaria"
PythonLF = "Nuova riga"
PythonTab = "Tabulazione"
PythonAmpersand = "Congiunzione"
PythonSymbolExp = "Disgiunzione esclusiva"
PythonVerticalBar = "Disgiunzione"
PythonImag = "Parte immaginaria di z"
PythonReal = "Parte reale di z"
PythonSingleQuote = "Apostrofo"
PythonAbs = "Valore assoluto/Modulo"
PythonAcos = "Coseno d'arco"
PythonAcosh = "Coseno iperbolico inverso"
PythonAppend = "Inserisce x alla fine della lista"
PythonArrow = "Freccia da (x,y) a (x+dx,y+dy)"
PythonAsin = "Arco sinusoidale"
PythonAsinh = "Arco sinusoidale iperbolico"
PythonAtan = "Arco tangente"
PythonAtan2 = "Calcolo di atan(y/x)"
PythonAtanh = "Arco tangente iperbolico"
PythonAxis = "Imposta assi (xmin,xmax,ymin,ymax)"
PythonBar = "Grafico a barre con x valori"
PythonBin = "Converte un intero in binario"
PythonCeil = "Parte intera superiore"
PythonChoice = "Numero aleatorio nella lista"
PythonClear = "Svuota la lista"
PythonCmathFunction = "Funz. prefissata modulo cmath"
PythonColor = "Definisci un colore rvb"
PythonColorBlack = "Colore nero"
PythonColorBlue = "Colore blu"
PythonColorBrown = "Colore marrone"
PythonColorGreen = "Colore verde"
PythonColorGrey = "Colore grigio"
PythonColorOrange = "Colore arancione"
PythonColorPink = "Colore rosa"
PythonColorPurple = "Colore viola"
PythonColorRed = "Colore rosso"
PythonColorWhite = "Colore bianco"
PythonColorYellow = "Colore giallo"
PythonComplex = "Restituisce a+ib"
PythonCopySign = "Restituisce x con segno di y"
PythonCos = "Coseno"
PythonCosh = "Coseno iperbolico"
PythonCount = "Conta le ricorrenze di x"
PythonDegrees = "Conversione di radianti in gradi"
PythonDivMod = "Quoziente e resto"
PythonDrawString = "Visualizza il testo dal pixel x,y"
PythonErf = "Funzione d'errore"
PythonErfc = "Funzione d'errore complementare"
PythonEval = "Valuta l'espressione nell'argomento "
PythonExp = "Funzione esponenziale"
PythonExpm1 = "Calcola exp(x)-1"
PythonFabs = "Valore assoluto"
PythonFillRect = "Riempie un rettangolo"
PythonFloat = "Conversione in flottanti"
PythonFloor = "Parte intera"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa ed esponente di x : (m,e)"
PythonGamma = "Funzione gamma"
PythonGetPixel = "Restituisce colore del pixel(x,y)"
PythonGetrandbits = "Numero aleatorio con k bit"
PythonGrid = "Attiva la visibilità della griglia"
PythonHex = "Conversione intero in esadecimale"
PythonHist = "Disegna l'istogramma di x"
PythonImportCmath = "Importa modulo cmath"
PythonImportIon = "Importa modulo ion"
PythonImportKandinsky = "Importa modulo kandinsky"
PythonImportRandom = "Importa modulo random"
PythonImportMath = "Importa modulo math"
PythonImportMatplotlibPyplot = "Importa modulo matplotlib.pyplot"
PythonImportTurtle = "Importa del modulo turtle"
PythonImportTime = "Importa del modulo time"
PythonIndex = "Indice prima occorrenza di x"
PythonInput = "Inserire un valore"
PythonInsert = "Inserire x in posizione i-esima"
PythonInt = "Conversione in intero"
PythonIonFunction = "Prefisso di funzione modulo ion"
PythonIsFinite = "Testa se x è finito"
PythonIsInfinite = "Testa se x est infinito"
PythonIsKeyDown = "Restituisce True premendo tasto k"
PythonIsNaN = "Testa se x è NaN"
PythonKandinskyFunction = "Prefisso funzione modulo kandinsky"
PythonKeyLeft = "Tasto FRECCIA SINISTRA"
PythonKeyUp = "Tasto FRECCIA ALTO"
PythonKeyDown = "Tasto FRECCIA BASSO"
PythonKeyRight = "Tasto FRECCIA DESTRA"
PythonKeyOk = "Tasto OK"
PythonKeyBack = "Tasto INDIETRO"
PythonKeyHome = "Tasto CASA"
PythonKeyOnOff = "Tasto ON/OFF"
PythonKeyShift = "Tasto SHIFT"
PythonKeyAlpha = "Tasto ALPHA"
PythonKeyXnt = "Tasto X,N,T"
PythonKeyVar = "Tasto VAR"
PythonKeyToolbox = "Tasto TOOLBOX"
PythonKeyBackspace = "Tasto CANCELLA"
PythonKeyExp = "Tasto ESPONENZIALE"
PythonKeyLn = "Tasto LOGARITMO NEPERIANO"
PythonKeyLog = "Tasto LOGARITMO DECIMALE"
PythonKeyImaginary = "Tasto I IMMAGINE"
PythonKeyComma = "Tasto VIRGOLA"
PythonKeyPower = "Tasto POTENZA"
PythonKeySine = "Tasto SENO"
PythonKeyCosine = "Tasto COSENO"
PythonKeyTangent = "Tasto TANGENTE"
PythonKeyPi = "Tasto PI"
PythonKeySqrt = "Tasto RADICE QUADRATA"
PythonKeySquare = "Tasto QUADRATO"
PythonKeySeven = "Tasto 7"
PythonKeyEight = "Tasto 8"
PythonKeyNine = "Tasto 9"
PythonKeyLeftParenthesis = "Tasto PARENTESI SINISTRA"
PythonKeyRightParenthesis = "Tasto PARENTESI DESTRA"
PythonKeyFour = "Tasto 4"
PythonKeyFive = "Tasto 5"
PythonKeySix = "Tasto 6"
PythonKeyMultiplication = "Tasto MOLTIPLICAZIONE"
PythonKeyDivision = "Tasto DIVISIONE"
PythonKeyOne = "Tasto 1"
PythonKeyTwo = "Tasto 2"
PythonKeyThree = "Tasto 3"
PythonKeyPlus = "Tasto PIÙ"
PythonKeyMinus = "Tasto MENO"
PythonKeyZero = "Tasto 0"
PythonKeyDot = "Tasto PUNTO"
PythonKeyEe = "Tasto 10 POTENZA X"
PythonKeyAns = "Tasto ANS"
PythonKeyExe = "Tasto EXE"
PythonLdexp = "Inversa di frexp : x*(2**i)"
PythonLength = "Longhezza di un oggetto"
PythonLgamma = "Logaritmo della funzione gamma"
PythonLog = "Logaritmo di base a"
PythonLog10 = "Logaritmo decimale"
PythonLog2 = "Logaritmo di base 2"
PythonMathFunction = "Prefisso funzione del modulo math"
PythonMatplotlibPyplotFunction = "Prefisso modulo matplotlib.pyplot"
PythonMax = "Massimo"
PythonMin = "Minimo"
PythonModf = "Parti frazionarie e intere"
PythonMonotonic = "Restituisce il valore dell'orologio"
PythonOct = "Conversione in ottale"
PythonPhase = "Argomento di z"
PythonPlot = "Disegna y in f. di x come linee"
PythonPolar = "Conversione in polare"
PythonPop = "Cancella l'ultimo elemento"
PythonPower = "x alla potenza y"
PythonPrint = "Visualizza l'oggetto"
PythonRadians = "Conversione da gradi a radianti"
PythonRandint = "Intero aleatorio in [a,b]"
PythonRandom = "Numero aleatorio in [0,1["
PythonRandomFunction = "Prefisso funzione modulo casuale"
PythonRandrange = "Numero dentro il range(start, stop)"
PythonRangeStartStop = "Lista da start a stop-1"
PythonRangeStop = "Lista da 0 a stop-1"
PythonRect = "Converte in coordinate algebriche"
PythonRemove = "Cancella la prima x dalla lista"
PythonReverse = "Inverte gli elementi della lista"
PythonRound = "Arrotondato a n cifre decimali"
PythonScatter = "Diagramma dispersione y in f. di x"
PythonSeed = "Inizializza il generatore random"
PythonSetPixel = "Colora il pixel (x,y)"
PythonShow = "Mostra la figura"
PythonSin = "Seno"
PythonSinh = "Seno iperbolico"
PythonSleep = "Sospende l'esecuzione t secondi"
PythonSort = "Ordina l'elenco"
PythonSqrt = "Radice quadrata"
PythonSum = "Somma degli elementi della lista"
PythonTan = "Tangente"
PythonTanh = "Tangente iperbolica"
PythonText = "Mostra un testo in (x,y)"
PythonTimeFunction = "Prefisso funzione modulo time"
PythonTrunc = "Troncamento intero"
PythonTurtleBackward = "Indietreggia di x pixels"
PythonTurtleCircle = "Cerchio di raggio r pixel"
PythonTurtleColor = "Modifica il colore del tratto"
PythonTurtleColorMode = "Imposta modalità colore a 1.0 o 255"
PythonTurtleForward = "Avanza di x pixel"
PythonTurtleFunction = "Prefisso funzione modello turtle"
PythonTurtleGoto = "Spostati alle coordinate (x,y)"
PythonTurtleHeading = "Restituisce l'orientamento attuale"
PythonTurtleHideturtle = "Nascondi la tartaruga"
PythonTurtleIsdown = "True se la penna è abbassata"
PythonTurtleLeft = "Ruota di a gradi a sinistra"
PythonTurtlePendown = "Abbassa la penna"
PythonTurtlePensize = "Dimensione del tratto in pixel"
PythonTurtlePenup = "Solleva la penna"
PythonTurtlePosition = "Fornisce posizione corrente (x,y)"
PythonTurtleReset = "Azzera il disegno"
PythonTurtleRight = "Ruota di a gradi a destra"
PythonTurtleSetheading = "Imposta l'orientamento per a gradi"
PythonTurtleSetposition = "Posiziona la tartaruga"
PythonTurtleShowturtle = "Mostra la tartaruga"
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
PythonTurtleWrite = "Mostra un testo"
PythonUniform = "Numero decimale tra [a,b]"

197
apps/code/catalog.nl.i18n Normal file
View File

@@ -0,0 +1,197 @@
PythonPound = "Opmerkingen"
PythonPercent = "Modulo"
Python1J = "Imaginaire i"
PythonLF = "Nieuwe regel"
PythonTab = "Tabulatie"
PythonAmpersand = "Bitsgewijze en"
PythonSymbolExp = "Bitsgewijze exclusieve of"
PythonVerticalBar = "Bitsgewijze of"
PythonImag = "Imaginair deel van z"
PythonReal = "Reëel deel van z"
PythonSingleQuote = "Enkele aanhalingstekens"
PythonAbs = "Absolute waarde"
PythonAcos = "Arccosinus"
PythonAcosh = "Arccosinus hyperbolicus"
PythonAppend = "Voeg x toe aan het eind van je lijst"
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
PythonAsin = "Arcsinus"
PythonAsinh = "Arcsinus hyperbolicus"
PythonAtan = "Arctangens"
PythonAtan2 = "Geeft atan(y/x)"
PythonAtanh = "Arctangens hyperbolicus"
PythonAxis = "Set the axes to (xmin,xmax,ymin,ymax)"
PythonBar = "Draw a bar plot with x values"
PythonBin = "Zet integer om in een binair getal"
PythonCeil = "Plafond"
PythonChoice = "Geeft willek. getal van de lijst"
PythonClear = "Lijst leegmaken"
PythonCmathFunction = "cmath module voorvoegsel"
PythonColor = "Definieer een rgb kleur"
PythonColorBlack = "Zwarte kleur"
PythonColorBlue = "Blauwe kleur"
PythonColorBrown = "Bruine kleur"
PythonColorGreen = "Groene kleur"
PythonColorGrey = "Grijze kleur"
PythonColorOrange = "Oranje kleur"
PythonColorPink = "Roze kleur"
PythonColorPurple = "Paarse kleur"
PythonColorRed = "Rode kleur"
PythonColorWhite = "Witte kleur"
PythonColorYellow = "Gele kleur"
PythonComplex = "Geeft a+ib"
PythonCopySign = "Geeft x met het teken van y"
PythonCos = "Cosinus"
PythonCosh = "Cosinus hyperbolicus"
PythonCount = "Tel voorkomen van x"
PythonDegrees = "Zet x om van radialen naar graden"
PythonDivMod = "Quotiënt en rest"
PythonDrawString = "Geef een tekst weer van pixel (x,y)"
PythonErf = "Error functie"
PythonErfc = "Complementaire error functie"
PythonEval = "Geef de geëvalueerde uitdrukking"
PythonExp = "Exponentiële functie"
PythonExpm1 = "Bereken exp(x)-1"
PythonFabs = "Absolute waarde"
PythonFillRect = "Vul een rechthoek bij pixel (x,y)"
PythonFloat = "Zet x om in een float"
PythonFloor = "Vloer"
PythonFmod = "a modulo b"
PythonFrExp = "Mantisse en exponent van x: (m,e)"
PythonGamma = "Gammafunctie"
PythonGetPixel = "Geef pixel (x,y) kleur (rgb)"
PythonGetrandbits = "Integer met k willekeurige bits"
PythonGrid = "Toggle the visibility of the grid"
PythonHex = "Zet integer om in hexadecimaal"
PythonHist = "Draw the histogram of x"
PythonImportCmath = "Importeer cmath module"
PythonImportIon = "Importeer ion module"
PythonImportKandinsky = "Importeer kandinsky module"
PythonImportRandom = "Importeer random module"
PythonImportMath = "Importeer math module"
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
PythonImportTime = "Importeer time module"
PythonImportTurtle = "Importeer turtle module"
PythonIndex = "Index van de eerste x aanwezigheden"
PythonInput = "Wijs een waarde toe"
PythonInsert = "Voeg x toe aan index i in de lijst"
PythonInt = "Zet x om in een integer"
PythonIonFunction = "ion module voorvoegsel"
PythonIsFinite = "Controleer of x eindig is"
PythonIsInfinite = "Controleer of x oneindig is"
PythonIsKeyDown = "Geef True als k toets omlaag is"
PythonIsNaN = "Controleer of x geen nummer is"
PythonKandinskyFunction = "kandinsky module voorvoegsel"
PythonKeyLeft = "PIJL NAAR LINKS toets"
PythonKeyUp = "PIJL OMHOOG toets"
PythonKeyDown = "PIJL OMLAAG toets"
PythonKeyRight = "PIJL NAAR RECHTS toets"
PythonKeyOk = "OK toets"
PythonKeyBack = "TERUG toets"
PythonKeyHome = "HOME toets"
PythonKeyOnOff = "AAN/UIT toets"
PythonKeyShift = "SHIFT toets"
PythonKeyAlpha = "ALPHA toets"
PythonKeyXnt = "X,N,T toets"
PythonKeyVar = "VAR toets"
PythonKeyToolbox = "TOOLBOX toets"
PythonKeyBackspace = "BACKSPACE toets"
PythonKeyExp = "EXPONENTIEEL toets"
PythonKeyLn = "NATUURLIJKE LOGARITME toets"
PythonKeyLog = "BRIGGSE LOGARITME toets"
PythonKeyImaginary = "IMAGINAIRE I toets"
PythonKeyComma = "KOMMA toets"
PythonKeyPower = "MACHT toets"
PythonKeySine = "SINUS toets"
PythonKeyCosine = "COSINUS toets"
PythonKeyTangent = "TANGENS toets"
PythonKeyPi = "PI toets"
PythonKeySqrt = "VIERKANTSWORTEL toets"
PythonKeySquare = "KWADRAAT toets"
PythonKeySeven = "7 toets"
PythonKeyEight = "8 toets"
PythonKeyNine = "9 toets"
PythonKeyLeftParenthesis = "HAAKJE OPENEN toets"
PythonKeyRightParenthesis = "HAAKJE SLUITEN toets"
PythonKeyFour = "4 toets"
PythonKeyFive = "5 toets"
PythonKeySix = "6 toets"
PythonKeyMultiplication = "VERMENIGVULDIGEN toets"
PythonKeyDivision = "DELEN toets"
PythonKeyOne = "1 toets"
PythonKeyTwo = "2 toets"
PythonKeyThree = "3 toets"
PythonKeyPlus = "PLUS toets"
PythonKeyMinus = "MIN toets"
PythonKeyZero = "0 toets"
PythonKeyDot = "PUNT toets"
PythonKeyEe = "10 TOT DE MACHT X toets"
PythonKeyAns = "ANS toets"
PythonKeyExe = "EXE toets"
PythonLdexp = "Geeft x*(2**i), inversie van frexp"
PythonLength = "Lengte van een object"
PythonLgamma = "Log-gammafunctie"
PythonLog = "Logaritme met grondgetal a"
PythonLog10 = "Logaritme met grondgetal 10"
PythonLog2 = "Logaritme met grondgetal 2"
PythonMathFunction = "math module voorvoegsel"
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
PythonMax = "Maximum"
PythonMin = "Minimum"
PythonModf = "Fractionele en gehele delen van x"
PythonMonotonic = "Waarde van een monotone klok"
PythonOct = "Integer omzetten naar octaal"
PythonPhase = "Fase van z in radialen"
PythonPlot = "Plot y versus x as lines"
PythonPolar = "z in poolcoördinaten"
PythonPop = "Verwijder en breng het laatste item terug"
PythonPower = "x tot de macht y"
PythonPrint = "Print object"
PythonRadians = "Zet x om van graden naar radialen"
PythonRandint = "Geeft willek. integer in [a,b]"
PythonRandom = "Een willekeurig getal in [0,1["
PythonRandomFunction = "random module voorvoegsel"
PythonRandrange = "Willek. getal in range(start, stop)"
PythonRangeStartStop = "Lijst van start tot stop-1"
PythonRangeStop = "Lijst van 0 tot stop-1"
PythonRect = "z in cartesiaanse coördinaten"
PythonRemove = "Verwijder het eerste voorkomen van x"
PythonReverse = "Keer de elementen van de lijst om"
PythonRound = "Rond af op n cijfers"
PythonScatter = "Draw a scatter plot of y versus x"
PythonSeed = "Start willek. getallengenerator"
PythonSetPixel = "Kleur pixel (x,y)"
PythonShow = "Display the figure"
PythonSin= "Sinus"
PythonSinh = "Sinus hyperbolicus"
PythonSleep = "Stel executie voor t seconden uit"
PythonSort = "Sorteer de lijst"
PythonSqrt = "Vierkantswortel"
PythonSum = "Sommeer de items van een lijst"
PythonTan = "Tangens"
PythonTanh = "Tangens hyperbolicus"
PythonText = "Display a text at (x,y) coordinates"
PythonTimeFunction = "time module voorvoegsel"
PythonTrunc = "x afgeknot tot een integer"
PythonTurtleBackward = "Ga achterwaarts met x pixels"
PythonTurtleCircle = "Cirkel van straal r pixels"
PythonTurtleColor = "Stel de kleur van de pen in"
PythonTurtleColorMode = "Stel de kleurmodus in op 1.0 of 255"
PythonTurtleForward = "Ga voorwaarts met x pixels"
PythonTurtleFunction = "turtle module voorvoegsel"
PythonTurtleGoto = "Verplaats naar (x,y) coordinaten"
PythonTurtleHeading = "Ga terug naar de huidige koers"
PythonTurtleHideturtle = "Verberg de schildpad"
PythonTurtleIsdown = "Geeft True als pen naar beneden is"
PythonTurtleLeft = "Ga linksaf met a graden"
PythonTurtlePendown = "Zet de pen naar beneden"
PythonTurtlePensize = "Stel de lijndikte in op x pixels"
PythonTurtlePenup = "Zet de pen omhoog"
PythonTurtlePosition = "Zet huidige (x,y) locatie terug"
PythonTurtleReset = "Reset de tekening"
PythonTurtleRight = "Ga rechtsaf met a graden"
PythonTurtleSetheading = "Zet de oriëntatie op a graden"
PythonTurtleSetposition = "Plaats de schildpad"
PythonTurtleShowturtle = "Laat de schildpad zien"
PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10"
PythonTurtleWrite = "Display a text"
PythonUniform = "Zwevendekommagetal in [a,b]"

View File

@@ -1,208 +1,204 @@
PythonPound = "Comment"
PythonPercent = "Modulo"
Python1J = "Imaginary i"
PythonLF = "Line feed"
PythonTab = "Tabulation"
PythonAmpersand = "Bitwise and"
PythonSymbolExp = "Bitwise exclusive or"
PythonVerticalBar = "Bitwise or"
PythonSingleQuote = "Single quote"
PythonImag = "Imaginary part of z"
PythonReal = "Real part of z"
PythonAbs = "Absolute value/Magnitude"
PythonAcos = "Arc cosine"
PythonAcosh = "Arc hyperbolic cosine"
PythonAppend = "Add x to the end of the list"
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
PythonAsin = "Arc sine"
PythonAsinh = "Arc hyperbolic sine"
PythonAtan = "Arc tangent"
PythonAtan2 = "Return atan(y/x)"
PythonAtanh = "Arc hyperbolic tangent"
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
PythonBar = "Draw a bar plot with x values"
PythonBin = "Convert integer to binary"
PythonCeil = "Ceiling"
PythonChoice = "Random number in the list"
PythonClear = "Empty the list"
PythonCmathFunction = "cmath module function prefix"
PythonColor = "Define a rgb color"
PythonComplex = "Return a+ib"
PythonCopySign = "Return x with the sign of y"
PythonCos = "Cosine"
PythonCosh = "Hyperbolic cosine"
PythonCount = "Count the occurrences of x"
PythonDegrees = "Convert x from radians to degrees"
PythonDivMod = "Quotient and remainder"
PythonDrawString = "Display a text from pixel (x,y)"
PythonErf = "Error function"
PythonErfc = "Complementary error function"
PythonEval = "Return the evaluated expression"
PythonExp = "Exponential function"
PythonExpm1 = "Compute exp(x)-1"
PythonFabs = "Absolute value"
PythonFillRect = "Fill a rectangle at pixel (x,y)"
PythonFloat = "Convert x to a float"
PythonFloor = "Floor"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa and exponent of x"
PythonGamma = "Gamma function"
PythonGetPixel = "Return pixel (x,y) color"
PythonGetrandbits = "Integer with k random bits"
PythonGrid = "Toggle the visibility of the grid"
PythonHex = "Convert integer to hexadecimal"
PythonHist = "Draw the histogram of x"
PythonImportCmath = "Import cmath module"
PythonImportIon = "Import ion module"
PythonImportKandinsky = "Import kandinsky module"
PythonImportRandom = "Import random module"
PythonImportMath = "Import math module"
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
PythonImportTime = "Import time module"
PythonImportTurtle = "Import turtle module"
PythonIndex = "Index of the first x occurrence"
PythonInput = "Prompt a value"
PythonInsert = "Insert x at index i in the list"
PythonInt = "Convert x to an integer"
PythonIonFunction = "ion module function prefix"
PythonIsFinite = "Check if x is finite"
PythonIsInfinite = "Check if x is infinity"
PythonIsKeyDown = "Return True if the k key is down"
PythonIsNaN = "Check if x is a NaN"
PythonKandinskyFunction = "kandinsky module function prefix"
PythonKeyLeft = "LEFT ARROW key"
PythonKeyUp = "UP ARROW key"
PythonKeyDown = "DOWN ARROW key"
PythonKeyRight = "RIGHT ARROW key"
PythonKeyOk = "OK key"
PythonKeyBack = "BACK key"
PythonKeyHome = "HOME key"
PythonKeyOnOff = "ON/OFF key"
PythonKeyShift = "SHIFT key"
PythonKeyAlpha = "ALPHA key"
PythonKeyXnt = "X,N,T key"
PythonKeyVar = "VAR key"
PythonKeyToolbox = "TOOLBOX key"
PythonKeyBackspace = "BACKSPACE key"
PythonKeyExp = "EXPONENTIAL key"
PythonKeyLn = "NATURAL LOGARITHM key"
PythonKeyLog = "DECIMAL LOGARITHM key"
PythonKeyImaginary = "IMAGINARY I key"
PythonKeyComma = "COMMA key"
PythonKeyPower = "POWER key"
PythonKeySine = "SINE key"
PythonKeyCosine = "COSINE key"
PythonKeyTangent = "TANGENT key"
PythonKeyPi = "PI key"
PythonKeySqrt = "SQUARE ROOT key"
PythonKeySquare = "SQUARE key"
PythonKeySeven = "7 key"
PythonKeyEight = "8 key"
PythonKeyNine = "9 key"
PythonKeyLeftParenthesis = "LEFT PARENTHESIS key"
PythonKeyRightParenthesis = "RIGHT PARENTHESIS key"
PythonKeyFour = "4 key"
PythonKeyFive = "5 key"
PythonKeySix = "6 key"
PythonKeyMultiplication = "MULTIPLICATION key"
PythonKeyDivision = "DIVISION key"
PythonKeyOne = "1 key"
PythonKeyTwo = "2 key"
PythonKeyThree = "3 key"
PythonKeyPlus = "PLUS key"
PythonKeyMinus = "MINUS key"
PythonKeyZero = "0 key"
PythonKeyDot = "DOT key"
PythonKeyEe = "10 POWER X key"
PythonKeyAns = "ANS key"
PythonKeyExe = "EXE key"
PythonLdexp = "Return x*(2**i), inverse of frexp"
PythonLength = "Length of an object"
PythonLgamma = "Log-gamma function"
PythonLog = "Logarithm to base a"
PythonLog10 = "Logarithm to base 10"
PythonLog2 = "Logarithm to base 2"
PythonMathFunction = "math module function prefix"
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
PythonMax = "Maximum"
PythonMin = "Minimum"
PythonModf = "Fractional and integer parts of x"
PythonMonotonic = "Value of a monotonic clock"
PythonOct = "Convert integer to octal"
PythonPhase = "Phase of z"
PythonPlot = "Plot y versus x as lines"
PythonPolar = "z in polar coordinates"
PythonPop = "Remove and return the last item"
PythonPower = "x raised to the power y"
PythonPrint = "Print object"
PythonRadians = "Convert x from degrees to radians"
PythonRandint = "Random integer in [a,b]"
PythonRandom = "Floating point number in [0,1["
PythonRandomFunction = "random module function prefix"
PythonRandrange = "Random number in range(start,stop)"
PythonRangeStartStop = "List from start to stop-1"
PythonRangeStop = "List from 0 to stop-1"
PythonRect = "Convert to cartesian coordinates"
PythonRemove = "Remove the first occurrence of x"
PythonReverse = "Reverse the elements of the list"
PythonRound = "Round to n digits"
PythonScatter = "Draw a scatter plot of y versus x"
PythonSeed = "Initialize random number generator"
PythonSetPixel = "Color pixel (x,y)"
PythonShow = "Display the figure"
PythonSin = "Sine"
PythonSinh = "Hyperbolic sine"
PythonSleep = "Suspend the execution for t seconds"
PythonSort = "Sort the list"
PythonSqrt = "Square root"
PythonSum = "Sum the items of a list"
PythonTan = "Tangent"
PythonTanh = "Hyperbolic tangent"
PythonText = "Display a text at (x,y) coordinates"
PythonTimeFunction = "time module function prefix"
PythonTrunc = "x truncated to an integer"
PythonTurtleBackward = "Move backward by x pixels"
PythonTurtleBlack = "Black color"
PythonTurtleBlue = "Blue color"
PythonTurtleBrown = "Brown color"
PythonTurtleCircle = "Circle of radius r pixels"
PythonTurtleColor = "Set the pen color"
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
PythonTurtleForward = "Move forward by x pixels"
PythonTurtleFunction = "turtle module function prefix"
PythonTurtleGoto = "Move to (x,y) coordinates"
PythonTurtleGreen = "Green color"
PythonTurtleGrey = "Grey color"
PythonTurtleHeading = "Return the current heading"
PythonTurtleHideturtle = "Hide the turtle"
PythonTurtleIsdown = "Return True if the pen is down"
PythonTurtleLeft = "Turn left by a degrees"
PythonTurtleOrange = "Orange color"
PythonTurtlePendown = "Pull the pen down"
PythonTurtlePensize = "Set the line thickness to x pixels"
PythonTurtlePenup = "Pull the pen up"
PythonTurtlePink = "Pink color"
PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtlePurple = "Purple color"
PythonTurtleRed = "Red color"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonPound = "Comentário"
PythonPercent = "Módulo"
Python1J = "i Complexo"
PythonLF = "Nova linha"
PythonTab = "Tabulação"
PythonAmpersand = "Operador binário and"
PythonSymbolExp = "Operador binário exclusivo or"
PythonVerticalBar = "Operador binário or"
PythonSingleQuote = "Apóstrofo"
PythonImag = "Parte imaginária de z"
PythonReal = "Parte real de z"
PythonAbs = "Valor absoluto/módulo"
PythonAcos = "Arco cosseno"
PythonAcosh = "Arco cosseno hiperbólico"
PythonAppend = "Adicionar x no fim da lista"
PythonArrow = "Seta de (x,y) para (x+dx,y+dy)"
PythonAsin = "Arco seno"
PythonAsinh = "Arco seno hiperbólico"
PythonAtan = "Arco tangente"
PythonAtan2 = "Cálculo de atan(y/x)"
PythonAtanh = "Arco tangente hiperbólica"
PythonAxis = "Definir eixos (xmin,xmax,ymin,ymax)"
PythonBar = "Gráfico de barras com valores de x"
PythonBin = "Converter número inteiro em binário"
PythonCeil = "Teto"
PythonChoice = "Número aleatório na lista"
PythonClear = "Esvaziar a lista"
PythonCmathFunction = "Prefixo da função do módulo cmath"
PythonColor = "Define uma cor rgb"
PythonColorBlack = "Cor preta"
PythonColorBlue = "Cor azul"
PythonColorBrown = "Cor castanha"
PythonColorGreen = "Cor verde"
PythonColorGrey = "Cor cinzenta"
PythonColorOrange = "Cor laranja"
PythonColorPink = "Cor rosa"
PythonColorPurple = "Cor roxa"
PythonColorRed = "Cor vermelha"
PythonColorWhite = "Cor branca"
PythonColorYellow = "Cor amarela"
PythonComplex = "Devolve a+ib"
PythonCopySign = "Devolve x com o sinal de y"
PythonCos = "Cosseno"
PythonCosh = "Cosseno hiperbólico"
PythonCount = "Contar as ocorrências de x"
PythonDegrees = "Converter x de radianos para graus"
PythonDivMod = "Quociente e resto"
PythonDrawString = "Mostrar o texto do pixel (x,y)"
PythonErf = "Função erro"
PythonErfc = "Função erro complementar"
PythonEval = "Devolve a expressão avaliada"
PythonExp = "Função exponencial"
PythonExpm1 = "Calcular exp(x)-1"
PythonFabs = "Valor absoluto"
PythonFillRect = "Preencher um retângulo em (x,y)"
PythonFloat = "Converter x num flutuante"
PythonFloor = "Parte inteira"
PythonFmod = "a módulo b"
PythonFrExp = "Coeficiente e expoente de x: (m, e)"
PythonGamma = "Função gama"
PythonGetPixel = "Devolve a cor do pixel (x,y)"
PythonGetrandbits = "Número inteiro aleatório com k bits"
PythonGrid = "Alterar visibilidade da grelha"
PythonHex = "Converter inteiro em hexadecimal"
PythonHist = "Desenhar o histograma de x"
PythonImportCmath = "Importar módulo cmath"
PythonImportIon = "Importar módulo ion"
PythonImportKandinsky = "Importar módulo kandinsky"
PythonImportRandom = "Importar módulo random"
PythonImportMath = "Importar módulo math"
PythonImportMatplotlibPyplot = "Importar módulo matplotlib.pyplot"
PythonImportTime = "Importar módulo time"
PythonImportTurtle = "Importar módulo turtle"
PythonIndex = "Índice da primeira ocorrência de x"
PythonInput = "Adicionar um valor"
PythonInsert = "Inserir x no índice i na lista"
PythonInt = "Converter x num número inteiro"
PythonIonFunction = "Prefixo da função do módulo ion"
PythonIsFinite = "Verificar se x é finito"
PythonIsInfinite = "Verificar se x é infinito"
PythonIsKeyDown = "Devolve True se tecla k pressionada"
PythonIsNaN = "Verificar se x é um NaN"
PythonKandinskyFunction = "Prefixo da função do módulo kandinsky"
PythonKeyLeft = "tecla SETA ESQUERDA"
PythonKeyUp = "tecla SETA CIMA "
PythonKeyDown = "tecla SETA BAIXO"
PythonKeyRight = "tecla SETA DIREITA"
PythonKeyOk = "tecla OK"
PythonKeyBack = "tecla VOLTAR"
PythonKeyHome = "tecla HOME"
PythonKeyOnOff = "tecla ON/OFF"
PythonKeyShift = "tecla SHIFT"
PythonKeyAlpha = "tecla ALPHA"
PythonKeyXnt = "tecla X,N,T"
PythonKeyVar = "tecla VAR"
PythonKeyToolbox = "tecla CAIXA DE FERRAMENTAS"
PythonKeyBackspace = "tecla APAGAR"
PythonKeyExp = "tecla EXPONENCIAL"
PythonKeyLn = "tecla LOGARITMO NATURAL"
PythonKeyLog = "tecla LOGARITMO DECIMAL"
PythonKeyImaginary = "tecla I IMAGINÁRIO"
PythonKeyComma = "tecla VÍRGULA"
PythonKeyPower = "tecla EXPOENTE"
PythonKeySine = "tecla SENO"
PythonKeyCosine = "tecla COSSENO"
PythonKeyTangent = "tecla TANGENTE"
PythonKeyPi = "tecla PI"
PythonKeySqrt = "tecla RAIZ QUADRADA"
PythonKeySquare = "tecla AO QUADRADO"
PythonKeySeven = "tecla 7"
PythonKeyEight = "tecla 8"
PythonKeyNine = "tecla 9"
PythonKeyLeftParenthesis = "tecla PARÊNTESE ESQUERDO"
PythonKeyRightParenthesis = "tecla PARÊNTESE DIREITO"
PythonKeyFour = "tecla 4"
PythonKeyFive = "tecla 5"
PythonKeySix = "tecla 6"
PythonKeyMultiplication = "tecla MULTIPLICAÇÃO"
PythonKeyDivision = "tecla DIVISÃO"
PythonKeyOne = "tecla 1"
PythonKeyTwo = "tecla 2"
PythonKeyThree = "tecla 3"
PythonKeyPlus = "tecla MAIS"
PythonKeyMinus = "tecla MENOS"
PythonKeyZero = "tecla 0"
PythonKeyDot = "tecla PONTO"
PythonKeyEe = "tecla 10 expoente X"
PythonKeyAns = "tecla ANS"
PythonKeyExe = "tecla EXE"
PythonLdexp = "Devolve x*(2**i), inverso de frexp"
PythonLength = "Comprimento de um objeto"
PythonLgamma = "Logaritmo da função gama"
PythonLog = "Logaritmo de base a"
PythonLog10 = "Logaritmo de base 10"
PythonLog2 = "Logaritmo de base 2"
PythonMathFunction = "Prefixo da função do módulo math"
PythonMatplotlibPyplotFunction = "Prefixo do módulo matplotlib.pyplot"
PythonMax = "Máximo"
PythonMin = "Mínimo"
PythonModf = "Partes inteira e frácionária de x"
PythonMonotonic = "Devolve o valor do relógio"
PythonOct = "Converter número inteiro em octal"
PythonPhase = "Argumento de z"
PythonPlot = "Desenhar y em função de x"
PythonPolar = "z em coordenadas polares"
PythonPop = "Remover o último item"
PythonPower = "x levantado a y"
PythonPrint = "Mostrar o objeto"
PythonRadians = "Converter x de graus para radianos"
PythonRandint = "Número inteiro aleatório em [a,b]"
PythonRandom = "Número decimal em [0,1["
PythonRandomFunction = "Prefixo da função do módulo random"
PythonRandrange = "Número aleatório em [start,stop-1]"
PythonRangeStartStop = "Lista de start a stop-1"
PythonRangeStop = "Lista de 0 a stop-1"
PythonRect = "Converter para coordenadas cartesianas"
PythonRemove = "Remover a primeira ocorrência de x"
PythonReverse = "Inverter os elementos da lista"
PythonRound = "Arredondar para n dígitos"
PythonScatter = "Gráfico de dispersão (x,y)"
PythonSeed = "Iniciar gerador aleatório"
PythonSetPixel = "Cor do pixel (x,y)"
PythonShow = "Mostrar a figura"
PythonSin = "Seno"
PythonSinh = "Seno hiperbólico"
PythonSleep = "Suspender a execução por t segundos"
PythonSort = "Ordenar a lista"
PythonSqrt = "Raiz quadrada"
PythonSum = "Soma dos itens da lista"
PythonTan = "Tangente"
PythonTanh = "Tangente hiperbólica"
PythonText = "Mostrar um texto em (x,y)"
PythonTimeFunction = "Prefixo da função do módulo time"
PythonTrunc = "x truncado a um número inteiro"
PythonTurtleBackward = "Recuar x pixels"
PythonTurtleCircle = "Circunferência de raio r pixels"
PythonTurtleColor = "Definir a cor da caneta"
PythonTurtleColorMode = "Define modo de cor para 1.0 ou 255"
PythonTurtleForward = "Avançar x pixels"
PythonTurtleFunction = "Prefixo da função do módulo turtle"
PythonTurtleGoto = "Ir paras as coordenadas (x,y)"
PythonTurtleHeading = "Voltar para a orientação atual"
PythonTurtleHideturtle = "Esconder o turtle"
PythonTurtleIsdown = "True se a caneta está pressionada"
PythonTurtleLeft = "Vira à esquerda por a graus"
PythonTurtlePendown = "Puxar a caneta para baixo"
PythonTurtlePensize = "Definir a espessura para x pixels"
PythonTurtlePenup = "Puxar a caneta para cima"
PythonTurtlePosition = "Devolve a posição atual (x,y)"
PythonTurtleReset = "Reiniciar o desenho"
PythonTurtleRight = "Virar à esquerda por a graus"
PythonTurtleSetheading = "Definir a orientação por a graus"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWhite = "White color"
PythonTurtleYellow = "Yellow color"
PythonUniform = "Floating point number in [a,b]"
PythonTimeFromImport = "Import time module"
PythonTimeImport = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Aguardar n segundos"
PythonTimeMonotonic = "Retornar tempo monotônico"
PythonTurtleShowturtle = "Mostrar o turtle"
PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10"
PythonTurtleWrite = "Mostrar um texto"
PythonUniform = "Número decimal em [a,b]"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"
PythonFileSeek = "Move file's internal cursor"
PythonFileTell = "Get file's internal cursor location"
PythonFileSeek = "Move file's cursor"
PythonFileTell = "Get file's cursor location"
PythonFileClose = "Closes a file"
PythonFileClosed = "True if file was closed"
PythonFileRead = "Read up to size bytes"

View File

@@ -29,6 +29,17 @@ PythonCommandClearWithoutArg = ".clear()"
PythonCommandCmathFunction = "cmath.function"
PythonCommandCmathFunctionWithoutArg = "cmath.\x11"
PythonCommandColor = "color(r,g,b)"
PythonCommandColorBlack = "'black'"
PythonCommandColorBlue = "'blue'"
PythonCommandColorBrown = "'brown'"
PythonCommandColorGreen = "'green'"
PythonCommandColorGrey = "'grey'"
PythonCommandColorOrange = "'orange'"
PythonCommandColorPink = "'pink'"
PythonCommandColorPurple = "'purple'"
PythonCommandColorRed = "'red'"
PythonCommandColorWhite = "'white'"
PythonCommandColorYellow = "'yellow'"
PythonCommandComplex = "complex(a,b)"
PythonCommandConstantPi = "pi"
PythonCommandCopySign = "copysign(x,y)"
@@ -154,7 +165,7 @@ PythonCommandModf = "modf(x)"
PythonCommandMonotonic = "monotonic()"
PythonCommandOct = "oct(x)"
PythonCommandPhase = "phase(z)"
PythonCommandPlot = "plot(x,y)"
PythonCommandPlot = "plot(x,y,color)"
PythonCommandPolar = "polar(z)"
PythonCommandPop = "list.pop()"
PythonCommandPopWithoutArg = ".pop()"
@@ -202,29 +213,19 @@ PythonCommandUniform = "uniform(a,b)"
PythonConstantE = "2.718281828459045"
PythonConstantPi = "3.141592653589793"
PythonTurtleCommandBackward = "backward(x)"
PythonTurtleCommandBlack = "'black'"
PythonTurtleCommandBlue = "'blue'"
PythonTurtleCommandBrown = "'brown'"
PythonTurtleCommandCircle = "circle(r)"
PythonTurtleCommandColor = "color('c')/color(r,g,b)"
PythonTurtleCommandColorWithoutArg = "color(\x11)"
PythonTurtleCommandColor = "color('c')"
PythonTurtleCommandColorMode = "colormode(x)"
PythonTurtleCommandForward = "forward(x)"
PythonTurtleCommandGoto = "goto(x,y)"
PythonTurtleCommandGreen = "'green'"
PythonTurtleCommandGrey = "'grey'"
PythonTurtleCommandHeading = "heading()"
PythonTurtleCommandHideturtle = "hideturtle()"
PythonTurtleCommandIsdown= "isdown()"
PythonTurtleCommandLeft = "left(a)"
PythonTurtleCommandOrange = "'orange'"
PythonTurtleCommandPendown = "pendown()"
PythonTurtleCommandPensize = "pensize(x)"
PythonTurtleCommandPenup = "penup()"
PythonTurtleCommandPink = "'pink'"
PythonTurtleCommandPosition = "position()"
PythonTurtleCommandPurple = "'purple'"
PythonTurtleCommandRed = "'red'"
PythonTurtleCommandReset = "reset()"
PythonTurtleCommandRight = "right(a)"
PythonTurtleCommandSetheading = "setheading(a)"
@@ -270,3 +271,4 @@ PythonCommandFileReadable = "file.readable()"
PythonCommandFileReadableWithoutArg = ".readable()"
PythonCommandFileWritable = "file.writable()"
PythonCommandFileWritableWithoutArg = ".writable()"
PythonTurtleCommandWrite = "write(\"text\")"

View File

@@ -31,7 +31,7 @@ ConsoleController::ConsoleController(Responder * parentResponder, App * pythonDe
m_pythonDelegate(pythonDelegate),
m_importScriptsWhenViewAppears(false),
m_selectableTableView(this, this, this, this),
m_editCell(this, pythonDelegate, this),
m_editCell(this, this, this),
m_scriptStore(scriptStore),
m_sandboxController(this),
m_inputRunLoopActive(false)
@@ -48,17 +48,13 @@ ConsoleController::ConsoleController(Responder * parentResponder, App * pythonDe
}
bool ConsoleController::loadPythonEnvironment() {
if (m_pythonDelegate->isPythonUser(this)) {
return true;
if (!m_pythonDelegate->isPythonUser(this)) {
m_scriptStore->clearConsoleFetchInformation();
emptyOutputAccumulationBuffer();
m_pythonDelegate->initPythonWithUser(this);
MicroPython::registerScriptProvider(m_scriptStore);
m_importScriptsWhenViewAppears = m_autoImportScripts;
}
emptyOutputAccumulationBuffer();
m_pythonDelegate->initPythonWithUser(this);
MicroPython::registerScriptProvider(m_scriptStore);
m_importScriptsWhenViewAppears = m_autoImportScripts;
/* We load functions and variables names in the variable box before running
* any other python code to avoid failling to load functions and variables
* due to memory exhaustion. */
App::app()->variableBoxController()->loadFunctionsAndVariables();
return true;
}
@@ -290,7 +286,7 @@ void ConsoleController::willDisplayCellAtLocation(HighlightCell * cell, int i, i
}
}
void ConsoleController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) {
void ConsoleController::tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) {
if (withinTemporarySelection) {
return;
}
@@ -375,6 +371,14 @@ bool ConsoleController::textFieldDidAbortEditing(TextField * textField) {
return true;
}
VariableBoxController * ConsoleController::variableBoxForInputEventHandler(InputEventHandler * textInput) {
VariableBoxController * varBox = App::app()->variableBoxController();
varBox->loadVariablesImportedFromScripts();
varBox->setTitle(I18n::Message::FunctionsAndVariables);
varBox->setDisplaySubtitles(false);
return varBox;
}
void ConsoleController::resetSandbox() {
if (stackViewController()->topViewController() != sandbox()) {
return;
@@ -479,7 +483,7 @@ void ConsoleController::autoImportScript(Script script, bool force) {
* the sandbox. */
hideAnyDisplayedViewController();
if (script.importationStatus() || force) {
if (script.autoImportationStatus() || force) {
// Step 1 - Create the command "from scriptName import *".
assert(strlen(k_importCommand1) + strlen(script.fullName()) - strlen(ScriptStore::k_scriptExtension) - 1 + strlen(k_importCommand2) + 1 <= k_maxImportCommandSize);

View File

@@ -10,12 +10,14 @@
#include "console_store.h"
#include "sandbox_controller.h"
#include "script_store.h"
#include "variable_box_controller.h"
#include "../shared/input_event_handler_delegate.h"
namespace Code {
class App;
class ConsoleController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public SelectableTableViewDelegate, public TextFieldDelegate, public MicroPython::ExecutionEnvironment {
class ConsoleController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public SelectableTableViewDelegate, public TextFieldDelegate, public Shared::InputEventHandlerDelegate, public MicroPython::ExecutionEnvironment {
public:
ConsoleController(Responder * parentResponder, App * pythonDelegate, ScriptStore * scriptStore
#if EPSILON_GETOPT
@@ -52,7 +54,7 @@ public:
void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override;
// SelectableTableViewDelegate
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) override;
void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) override;
// TextFieldDelegate
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
@@ -60,6 +62,9 @@ public:
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
bool textFieldDidAbortEditing(TextField * textField) override;
// InputEventHandlerDelegate
VariableBoxController * variableBoxForInputEventHandler(InputEventHandler * textInput) override;
// MicroPython::ExecutionEnvironment
ViewController * sandbox() override { return &m_sandboxController; }
void resetSandbox() override;

View File

@@ -13,13 +13,15 @@ EditorController::EditorController(MenuController * menuController, App * python
ViewController(nullptr),
m_editorView(this, pythonDelegate),
m_script(Ion::Storage::Record()),
m_scriptIndex(-1),
m_menuController(menuController)
{
m_editorView.setTextAreaDelegates(this, this);
}
void EditorController::setScript(Script script) {
void EditorController::setScript(Script script, int scriptIndex) {
m_script = script;
m_scriptIndex = scriptIndex;
/* We edit the script direclty in the storage buffer. We thus put all the
* storage available space at the end of the current edited script and we set
@@ -35,7 +37,7 @@ void EditorController::setScript(Script script) {
* */
size_t newScriptSize = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(m_script);
m_editorView.setText(const_cast<char *>(m_script.scriptContent()), newScriptSize - Script::k_importationStatusSize);
m_editorView.setText(const_cast<char *>(m_script.content()), newScriptSize - Script::StatusSize());
}
void EditorController::willExitApp() {
@@ -131,7 +133,24 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
VariableBoxController * EditorController::variableBoxForInputEventHandler(InputEventHandler * textInput) {
VariableBoxController * varBox = App::app()->variableBoxController();
varBox->loadFunctionsAndVariables();
/* If the editor should be autocompleting an identifier, the variable box has
* already been loaded. We check shouldAutocomplete and not isAutocompleting,
* because the autocompletion result might be empty. */
const char * beginningOfAutocompletion = nullptr;
const char * cursor = nullptr;
PythonTextArea::AutocompletionType autocompType = m_editorView.autocompletionType(&beginningOfAutocompletion, &cursor);
if (autocompType == PythonTextArea::AutocompletionType::NoIdentifier) {
varBox->loadFunctionsAndVariables(m_scriptIndex, nullptr, 0);
} else if (autocompType == PythonTextArea::AutocompletionType::MiddleOfIdentifier) {
varBox->empty();
} else {
assert(autocompType == PythonTextArea::AutocompletionType::EndOfIdentifier);
assert(beginningOfAutocompletion != nullptr && cursor != nullptr);
assert(cursor > beginningOfAutocompletion);
varBox->loadFunctionsAndVariables(m_scriptIndex, beginningOfAutocompletion, cursor - beginningOfAutocompletion);
}
varBox->setTitle(I18n::Message::Autocomplete);
varBox->setDisplaySubtitles(true);
return varBox;
}
@@ -146,7 +165,7 @@ void EditorController::cleanStorageEmptySpace() {
Ion::Storage::Record::Data scriptValue = m_script.value();
Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(
m_script,
scriptValue.size - Script::k_importationStatusSize - (strlen(m_script.scriptContent()) + 1)); // TODO optimize number of script fetches
scriptValue.size - Script::StatusSize() - (strlen(m_script.content()) + 1)); // TODO optimize number of script fetches
}

View File

@@ -16,7 +16,8 @@ class App;
class EditorController : public ViewController, public TextAreaDelegate, public Shared::InputEventHandlerDelegate {
public:
EditorController(MenuController * menuController, App * pythonDelegate);
void setScript(Script script);
void setScript(Script script, int scriptIndex);
int scriptIndex() const { return m_scriptIndex; }
void willExitApp();
/* ViewController */
@@ -39,6 +40,7 @@ private:
StackViewController * stackController();
EditorView m_editorView;
Script m_script;
int m_scriptIndex;
MenuController * m_menuController;
};

View File

@@ -17,6 +17,10 @@ EditorView::EditorView(Responder * parentResponder, App * pythonDelegate) :
m_textArea.setScrollViewDelegate(this);
}
bool EditorView::isAutocompleting() const {
return m_textArea.isAutocompleting();
}
void EditorView::resetSelection() {
m_textArea.resetSelection();
}

View File

@@ -9,6 +9,8 @@ namespace Code {
class EditorView : public Responder, public View, public ScrollViewDelegate {
public:
EditorView(Responder * parentResponder, App * pythonDelegate);
PythonTextArea::AutocompletionType autocompletionType(const char ** autocompletionBeginning, const char ** autocompletionEnd) const { return m_textArea.autocompletionType(nullptr, autocompletionBeginning, autocompletionEnd); }
bool isAutocompleting() const;
void resetSelection();
void setTextAreaDelegates(InputEventHandlerDelegate * inputEventHandlerDelegate, TextAreaDelegate * delegate) {
m_textArea.setDelegates(inputEventHandlerDelegate, delegate);
@@ -17,6 +19,9 @@ public:
void setText(char * textBuffer, size_t textBufferSize) {
m_textArea.setText(textBuffer, textBufferSize);
}
const char * cursorLocation() {
return m_textArea.cursorLocation();
}
bool setCursorLocation(const char * location) {
return m_textArea.setCursorLocation(location);
}

View File

@@ -385,7 +385,7 @@ void MenuController::configureScript() {
void MenuController::editScriptAtIndex(int scriptIndex) {
assert(scriptIndex >=0 && scriptIndex < m_scriptStore->numberOfScripts());
Script script = m_scriptStore->scriptAtIndex(scriptIndex);
m_editorController.setScript(script);
m_editorController.setScript(script, scriptIndex);
stackViewController()->push(&m_editorController);
}

View File

@@ -25,6 +25,7 @@ public:
void openConsoleWithScript(Script script);
void scriptContentEditionDidFinish();
void willExitApp();
int editedScriptIndex() const { return m_editorController.scriptIndex(); }
/* ViewController */
View * view() override { return &m_selectableTableView; }

View File

@@ -21,6 +21,7 @@ constexpr KDColor OperatorColor = Palette::CodeOperator;
constexpr KDColor StringColor = Palette::CodeString;
constexpr KDColor BackgroundColor = Palette::CodeBackground;
constexpr KDColor HighlightColor = Palette::CodeBackgroundSelected;
constexpr KDColor AutocompleteColor = KDColor::RGB24(0xC6C6C6); // TODO Palette change
static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
if (tokenKind == MP_TOKEN_STRING) {
@@ -29,13 +30,96 @@ static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
if (tokenKind == MP_TOKEN_INTEGER || tokenKind == MP_TOKEN_FLOAT_OR_IMAG) {
return NumberColor;
}
static_assert(MP_TOKEN_ELLIPSIS + 1 == MP_TOKEN_KW_FALSE
&& MP_TOKEN_KW_FALSE + 1 == MP_TOKEN_KW_NONE
&& MP_TOKEN_KW_NONE + 1 == MP_TOKEN_KW_TRUE
&& MP_TOKEN_KW_TRUE + 1 == MP_TOKEN_KW___DEBUG__
&& MP_TOKEN_KW___DEBUG__ + 1 == MP_TOKEN_KW_AND
&& MP_TOKEN_KW_AND + 1 == MP_TOKEN_KW_AS
&& MP_TOKEN_KW_AS + 1 == MP_TOKEN_KW_ASSERT
/* Here there are keywords that depend on MICROPY_PY_ASYNC_AWAIT, we do
* not test them */
&& MP_TOKEN_KW_BREAK + 1 == MP_TOKEN_KW_CLASS
&& MP_TOKEN_KW_CLASS + 1 == MP_TOKEN_KW_CONTINUE
&& MP_TOKEN_KW_CONTINUE + 1 == MP_TOKEN_KW_DEF
&& MP_TOKEN_KW_DEF + 1 == MP_TOKEN_KW_DEL
&& MP_TOKEN_KW_DEL + 1 == MP_TOKEN_KW_ELIF
&& MP_TOKEN_KW_ELIF + 1 == MP_TOKEN_KW_ELSE
&& MP_TOKEN_KW_ELSE + 1 == MP_TOKEN_KW_EXCEPT
&& MP_TOKEN_KW_EXCEPT + 1 == MP_TOKEN_KW_FINALLY
&& MP_TOKEN_KW_FINALLY + 1 == MP_TOKEN_KW_FOR
&& MP_TOKEN_KW_FOR + 1 == MP_TOKEN_KW_FROM
&& MP_TOKEN_KW_FROM + 1 == MP_TOKEN_KW_GLOBAL
&& MP_TOKEN_KW_GLOBAL + 1 == MP_TOKEN_KW_IF
&& MP_TOKEN_KW_IF + 1 == MP_TOKEN_KW_IMPORT
&& MP_TOKEN_KW_IMPORT + 1 == MP_TOKEN_KW_IN
&& MP_TOKEN_KW_IN + 1 == MP_TOKEN_KW_IS
&& MP_TOKEN_KW_IS + 1 == MP_TOKEN_KW_LAMBDA
&& MP_TOKEN_KW_LAMBDA + 1 == MP_TOKEN_KW_NONLOCAL
&& MP_TOKEN_KW_NONLOCAL + 1 == MP_TOKEN_KW_NOT
&& MP_TOKEN_KW_NOT + 1 == MP_TOKEN_KW_OR
&& MP_TOKEN_KW_OR + 1 == MP_TOKEN_KW_PASS
&& MP_TOKEN_KW_PASS + 1 == MP_TOKEN_KW_RAISE
&& MP_TOKEN_KW_RAISE + 1 == MP_TOKEN_KW_RETURN
&& MP_TOKEN_KW_RETURN + 1 == MP_TOKEN_KW_TRY
&& MP_TOKEN_KW_TRY + 1 == MP_TOKEN_KW_WHILE
&& MP_TOKEN_KW_WHILE + 1 == MP_TOKEN_KW_WITH
&& MP_TOKEN_KW_WITH + 1 == MP_TOKEN_KW_YIELD
&& MP_TOKEN_KW_YIELD + 1 == MP_TOKEN_OP_TILDE,
"MP_TOKEN order changed, so Code::PythonTextArea::TokenColor might need to change too.");
if (tokenKind >= MP_TOKEN_KW_FALSE && tokenKind <= MP_TOKEN_KW_YIELD) {
return KeywordColor;
}
if (tokenKind >= MP_TOKEN_OP_PLUS && tokenKind <= MP_TOKEN_OP_NOT_EQUAL) {
return OperatorColor;
}
if (tokenKind >= MP_TOKEN_DEL_EQUAL && tokenKind <= MP_TOKEN_DEL_MINUS_MORE) {
static_assert(MP_TOKEN_OP_TILDE + 1 == MP_TOKEN_OP_LESS
&& MP_TOKEN_OP_LESS + 1 == MP_TOKEN_OP_MORE
&& MP_TOKEN_OP_MORE + 1 == MP_TOKEN_OP_DBL_EQUAL
&& MP_TOKEN_OP_DBL_EQUAL + 1 == MP_TOKEN_OP_LESS_EQUAL
&& MP_TOKEN_OP_LESS_EQUAL + 1 == MP_TOKEN_OP_MORE_EQUAL
&& MP_TOKEN_OP_MORE_EQUAL + 1 == MP_TOKEN_OP_NOT_EQUAL
&& MP_TOKEN_OP_NOT_EQUAL + 1 == MP_TOKEN_OP_PIPE
&& MP_TOKEN_OP_PIPE + 1 == MP_TOKEN_OP_CARET
&& MP_TOKEN_OP_CARET + 1 == MP_TOKEN_OP_AMPERSAND
&& MP_TOKEN_OP_AMPERSAND + 1 == MP_TOKEN_OP_DBL_LESS
&& MP_TOKEN_OP_DBL_LESS + 1 == MP_TOKEN_OP_DBL_MORE
&& MP_TOKEN_OP_DBL_MORE + 1 == MP_TOKEN_OP_PLUS
&& MP_TOKEN_OP_PLUS + 1 == MP_TOKEN_OP_MINUS
&& MP_TOKEN_OP_MINUS + 1 == MP_TOKEN_OP_STAR
&& MP_TOKEN_OP_STAR + 1 == MP_TOKEN_OP_AT
&& MP_TOKEN_OP_AT + 1 == MP_TOKEN_OP_DBL_SLASH
&& MP_TOKEN_OP_DBL_SLASH + 1 == MP_TOKEN_OP_SLASH
&& MP_TOKEN_OP_SLASH + 1 == MP_TOKEN_OP_PERCENT
&& MP_TOKEN_OP_PERCENT + 1 == MP_TOKEN_OP_DBL_STAR
&& MP_TOKEN_OP_DBL_STAR + 1 == MP_TOKEN_DEL_PIPE_EQUAL
&& MP_TOKEN_DEL_PIPE_EQUAL + 1 == MP_TOKEN_DEL_CARET_EQUAL
&& MP_TOKEN_DEL_CARET_EQUAL + 1 == MP_TOKEN_DEL_AMPERSAND_EQUAL
&& MP_TOKEN_DEL_AMPERSAND_EQUAL + 1 == MP_TOKEN_DEL_DBL_LESS_EQUAL
&& MP_TOKEN_DEL_DBL_LESS_EQUAL + 1 == MP_TOKEN_DEL_DBL_MORE_EQUAL
&& MP_TOKEN_DEL_DBL_MORE_EQUAL + 1 == MP_TOKEN_DEL_PLUS_EQUAL
&& MP_TOKEN_DEL_PLUS_EQUAL + 1 == MP_TOKEN_DEL_MINUS_EQUAL
&& MP_TOKEN_DEL_MINUS_EQUAL + 1 == MP_TOKEN_DEL_STAR_EQUAL
&& MP_TOKEN_DEL_STAR_EQUAL + 1 == MP_TOKEN_DEL_AT_EQUAL
&& MP_TOKEN_DEL_AT_EQUAL + 1 == MP_TOKEN_DEL_DBL_SLASH_EQUAL
&& MP_TOKEN_DEL_DBL_SLASH_EQUAL + 1 == MP_TOKEN_DEL_SLASH_EQUAL
&& MP_TOKEN_DEL_SLASH_EQUAL + 1 == MP_TOKEN_DEL_PERCENT_EQUAL
&& MP_TOKEN_DEL_PERCENT_EQUAL + 1 == MP_TOKEN_DEL_DBL_STAR_EQUAL
&& MP_TOKEN_DEL_DBL_STAR_EQUAL + 1 == MP_TOKEN_DEL_PAREN_OPEN
&& MP_TOKEN_DEL_PAREN_OPEN + 1 == MP_TOKEN_DEL_PAREN_CLOSE
&& MP_TOKEN_DEL_PAREN_CLOSE + 1 == MP_TOKEN_DEL_BRACKET_OPEN
&& MP_TOKEN_DEL_BRACKET_OPEN + 1 == MP_TOKEN_DEL_BRACKET_CLOSE
&& MP_TOKEN_DEL_BRACKET_CLOSE + 1 == MP_TOKEN_DEL_BRACE_OPEN
&& MP_TOKEN_DEL_BRACE_OPEN + 1 == MP_TOKEN_DEL_BRACE_CLOSE
&& MP_TOKEN_DEL_BRACE_CLOSE + 1 == MP_TOKEN_DEL_COMMA
&& MP_TOKEN_DEL_COMMA + 1 == MP_TOKEN_DEL_COLON
&& MP_TOKEN_DEL_COLON + 1 == MP_TOKEN_DEL_PERIOD
&& MP_TOKEN_DEL_PERIOD + 1 == MP_TOKEN_DEL_SEMICOLON
&& MP_TOKEN_DEL_SEMICOLON + 1 == MP_TOKEN_DEL_EQUAL
&& MP_TOKEN_DEL_EQUAL + 1 == MP_TOKEN_DEL_MINUS_MORE,
"MP_TOKEN order changed, so Code::PythonTextArea::TokenColor might need to change too.");
if ((tokenKind >= MP_TOKEN_OP_TILDE && tokenKind <= MP_TOKEN_DEL_DBL_STAR_EQUAL)
|| tokenKind == MP_TOKEN_DEL_EQUAL
|| tokenKind == MP_TOKEN_DEL_MINUS_MORE)
{
return OperatorColor;
}
return Palette::CodeText;
@@ -52,6 +136,76 @@ static inline size_t TokenLength(mp_lexer_t * lex, const char * tokenPosition) {
return lex->column - lex->tok_column;
}
PythonTextArea::AutocompletionType PythonTextArea::autocompletionType(const char * autocompletionLocation, const char ** autocompletionLocationBeginning, const char ** autocompletionLocationEnd) const {
const char * location = autocompletionLocation != nullptr ? autocompletionLocation : cursorLocation();
const char * beginningOfToken = nullptr;
/* If there is already autocompleting, the cursor must be at the end of an
* identifier. Trying to compute autocompletionType will fail: because of the
* autocompletion text, the cursor seems to be in the middle of an identifier. */
AutocompletionType autocompleteType = isAutocompleting() ? AutocompletionType::EndOfIdentifier : AutocompletionType::NoIdentifier;
if (autocompletionLocationBeginning == nullptr && autocompletionLocationEnd == nullptr) {
return autocompleteType;
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
const char * firstNonSpace = UTF8Helper::BeginningOfWord(m_contentView.editedText(), location);
mp_lexer_t * lex = mp_lexer_new_from_str_len(0, firstNonSpace, UTF8Helper::EndOfWord(location) - firstNonSpace, 0);
const char * tokenStart;
const char * tokenEnd;
_mp_token_kind_t currentTokenKind = lex->tok_kind;
while (currentTokenKind != MP_TOKEN_NEWLINE && currentTokenKind != MP_TOKEN_END) {
tokenStart = firstNonSpace + lex->tok_column - 1;
tokenEnd = tokenStart + TokenLength(lex, tokenStart);
if (location < tokenStart) {
// The location for autocompletion is not in an identifier
assert(autocompleteType == AutocompletionType::NoIdentifier);
break;
}
if (location <= tokenEnd) {
if (currentTokenKind == MP_TOKEN_NAME
|| (currentTokenKind >= MP_TOKEN_KW_FALSE
&& currentTokenKind <= MP_TOKEN_KW_YIELD))
{
/* The location for autocompletion is in the middle or at the end of
* an identifier. */
beginningOfToken = tokenStart;
/* If autocompleteType is already EndOfIdentifier, we are
* autocompleting, so we do not need to update autocompleteType. If we
* recomputed autocompleteType now, we might wrongly think that it is
* MiddleOfIdentifier because of the autocompetion text.
* Example : fin|ally -> the lexer is at the end of "fin", but because
* we are autocompleting with "ally", the lexer thinks the cursor is
* in the middle of an identifier. */
if (autocompleteType != AutocompletionType::EndOfIdentifier) {
autocompleteType = location < tokenEnd ? AutocompletionType::MiddleOfIdentifier : AutocompletionType::EndOfIdentifier;
}
}
break;
}
mp_lexer_to_next(lex);
currentTokenKind = lex->tok_kind;
}
mp_lexer_free(lex);
nlr_pop();
}
if (autocompletionLocationBeginning != nullptr) {
*autocompletionLocationBeginning = beginningOfToken;
}
if (autocompletionLocationEnd != nullptr) {
*autocompletionLocationEnd = location;
}
assert(!isAutocompleting() || autocompleteType == AutocompletionType::EndOfIdentifier);
return autocompleteType;
}
const char * PythonTextArea::ContentView::textToAutocomplete() const {
return UTF8Helper::BeginningOfWord(editedText(), cursorLocation());
}
void PythonTextArea::ContentView::loadSyntaxHighlighter() {
m_pythonDelegate->initPythonWithUser(this);
}
@@ -75,23 +229,7 @@ void PythonTextArea::ContentView::clearRect(KDContext * ctx, KDRect rect) const
void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char * text, size_t byteLength, int fromColumn, int toColumn, const char * selectionStart, const char * selectionEnd) const {
LOG_DRAW("Drawing \"%.*s\"\n", byteLength, text);
if (!m_pythonDelegate->isPythonUser(this)) {
const char * lineStart = UTF8Helper::CodePointAtGlyphOffset(text, fromColumn);
const char * lineEnd = UTF8Helper::CodePointAtGlyphOffset(text, toColumn);
drawStringAt(
ctx,
line,
fromColumn,
lineStart,
std::min(text + byteLength, lineEnd) - lineStart,
StringColor,
BackgroundColor,
selectionStart,
selectionEnd,
HighlightColor
);
return;
}
assert(m_pythonDelegate->isPythonUser(this));
/* We're using the MicroPython lexer to do syntax highlighting on a per-line
* basis. This can work, however the MicroPython lexer won't accept a line
@@ -117,6 +255,8 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
return;
}
const char * autocompleteStart = m_autocomplete ? m_cursorLocation : nullptr;
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_lexer_t * lex = mp_lexer_new_from_str_len(0, firstNonSpace, byteLength - (firstNonSpace - text), 0);
@@ -143,12 +283,16 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
}
tokenLength = TokenLength(lex, tokenFrom);
tokenEnd = tokenFrom + tokenLength;
// If the token is being autocompleted, use DefaultColor
KDColor color = (tokenFrom <= autocompleteStart && autocompleteStart < tokenEnd) ? Palette::CodeText : TokenColor(lex->tok_kind);
LOG_DRAW("Draw \"%.*s\" for token %d\n", tokenLength, tokenFrom, lex->tok_kind);
drawStringAt(ctx, line,
UTF8Helper::GlyphOffsetAtCodePoint(text, tokenFrom),
tokenFrom,
tokenLength,
TokenColor(lex->tok_kind),
color,
BackgroundColor,
selectionStart,
selectionEnd,
@@ -160,6 +304,7 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
tokenFrom += tokenLength;
// Even if the token is being autocompleted, use CommentColor
if (tokenFrom < text + byteLength) {
LOG_DRAW("Draw comment \"%.*s\" from %d\n", byteLength - (tokenFrom - text), firstNonSpace, tokenFrom);
drawStringAt(ctx, line,
@@ -176,6 +321,22 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
mp_lexer_free(lex);
nlr_pop();
}
// Redraw the autocompleted word in the right color
if (m_autocomplete && autocompleteStart >= text && autocompleteStart < text + byteLength) {
assert(m_autocompletionEnd != nullptr && m_autocompletionEnd > autocompleteStart);
drawStringAt(
ctx,
line,
UTF8Helper::GlyphOffsetAtCodePoint(text, autocompleteStart),
autocompleteStart,
std::min(text + byteLength, m_autocompletionEnd) - autocompleteStart,
AutocompleteColor,
BackgroundColor,
nullptr,
nullptr,
HighlightColor);
}
}
KDRect PythonTextArea::ContentView::dirtyRectFromPosition(const char * position, bool includeFollowingLines) const {
@@ -193,4 +354,158 @@ KDRect PythonTextArea::ContentView::dirtyRectFromPosition(const char * position,
);
}
bool PythonTextArea::handleEvent(Ion::Events::Event event) {
if (m_contentView.isAutocompleting()) {
// Handle event with autocompletion
if (event == Ion::Events::Right
|| event == Ion::Events::ShiftRight
|| event == Ion::Events::OK)
{
m_contentView.reloadRectFromPosition(m_contentView.cursorLocation(), false);
acceptAutocompletion(event != Ion::Events::ShiftRight);
if (event != Ion::Events::ShiftRight) {
// Do not process the event more
scrollToCursor();
return true;
}
} else if (event == Ion::Events::Toolbox
|| event == Ion::Events::Var
|| event == Ion::Events::Shift
|| event == Ion::Events::Alpha
|| event == Ion::Events::OnOff)
{
} else if(event == Ion::Events::Up
|| event == Ion::Events::Down)
{
cycleAutocompletion(event == Ion::Events::Down);
return true;
} else {
removeAutocompletion();
m_contentView.reloadRectFromPosition(m_contentView.cursorLocation(), false);
if (event == Ion::Events::Back) {
// Do not process the event more
return true;
}
}
}
bool result = TextArea::handleEvent(event);
if (event == Ion::Events::Backspace && !m_contentView.isAutocompleting() && selectionIsEmpty()) {
/* We want to add autocompletion when we are editing a word (after adding or
* deleting text). So if nothing is selected, we add the autocompletion if
* the event is backspace, as autocompletion has already been added if the
* event added text, in handleEventWithText. */
addAutocompletion();
}
return result;
}
bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
if (*text == 0) {
return false;
}
if (m_contentView.isAutocompleting()) {
removeAutocompletion();
}
bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText);
addAutocompletion();
return result;
}
void PythonTextArea::removeAutocompletion() {
assert(m_contentView.isAutocompleting());
removeAutocompletionText();
m_contentView.setAutocompleting(false);
}
void PythonTextArea::removeAutocompletionText() {
assert(m_contentView.isAutocompleting());
assert(m_contentView.autocompletionEnd() != nullptr);
const char * autocompleteStart = m_contentView.cursorLocation();
const char * autocompleteEnd = m_contentView.autocompletionEnd();
assert(autocompleteEnd != nullptr && autocompleteEnd > autocompleteStart);
m_contentView.removeText(autocompleteStart, autocompleteEnd);
}
void PythonTextArea::addAutocompletion() {
assert(!m_contentView.isAutocompleting());
const char * autocompletionTokenBeginning = nullptr;
const char * autocompletionLocation = const_cast<char *>(cursorLocation());
m_autocompletionResultIndex = 0;
if (autocompletionType(autocompletionLocation, &autocompletionTokenBeginning) != AutocompletionType::EndOfIdentifier) {
// The cursor is not at the end of an identifier.
return;
}
// First load variables and functions that complete the textToAutocomplete
const int scriptIndex = m_contentView.pythonDelegate()->menuController()->editedScriptIndex();
m_contentView.pythonDelegate()->variableBoxController()->loadFunctionsAndVariables(scriptIndex, autocompletionTokenBeginning, autocompletionLocation - autocompletionTokenBeginning);
if (addAutocompletionTextAtIndex(0)) {
m_contentView.setAutocompleting(true);
}
}
bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIndexToUpdate) {
// The variable box should be loaded at this point
const char * autocompletionTokenBeginning = nullptr;
const char * autocompletionLocation = const_cast<char *>(cursorLocation());
AutocompletionType type = autocompletionType(autocompletionLocation, &autocompletionTokenBeginning); // Done to get autocompletionTokenBeginning
assert(type == AutocompletionType::EndOfIdentifier);
(void)type; // Silence warnings
VariableBoxController * varBox = m_contentView.pythonDelegate()->variableBoxController();
int textToInsertLength = 0;
bool addParentheses = false;
const char * textToInsert = varBox->autocompletionAlternativeAtIndex(autocompletionLocation - autocompletionTokenBeginning, &textToInsertLength, &addParentheses, nextIndex, currentIndexToUpdate);
if (textToInsert == nullptr) {
return false;
}
if (textToInsertLength > 0) {
// Try to insert the text (this might fail if the buffer is full)
if (!m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength)) {
return false;
}
autocompletionLocation += textToInsertLength;
m_contentView.setAutocompletionEnd(autocompletionLocation);
}
// Try to insert the parentheses if needed
const char * parentheses = ScriptNodeCell::k_parentheses;
constexpr int parenthesesLength = 2;
assert(strlen(parentheses) == parenthesesLength);
/* If couldInsertText is false, we should not try to add the parentheses as
* there was already not enough space to add the autocompletion. */
if (addParentheses && m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength)) {
m_contentView.setAutocompleting(true);
m_contentView.setAutocompletionEnd(autocompletionLocation + parenthesesLength);
}
return true;
}
void PythonTextArea::cycleAutocompletion(bool downwards) {
assert(m_contentView.isAutocompleting());
removeAutocompletionText();
addAutocompletionTextAtIndex(m_autocompletionResultIndex + (downwards ? 1 : -1), &m_autocompletionResultIndex);
}
void PythonTextArea::acceptAutocompletion(bool moveCursorToEndOfAutocompletion) {
assert(m_contentView.isAutocompleting());
// Save the cursor location
const char * previousCursorLocation = cursorLocation();
removeAutocompletion();
m_contentView.pythonDelegate()->variableBoxController()->setSender(this);
m_contentView.pythonDelegate()->variableBoxController()->insertAutocompletionResultAtIndex(m_autocompletionResultIndex);
// insertAutocompletionResultAtIndex already added the autocompletion
// If we did not want to move the cursor, restore its position.
if (!moveCursorToEndOfAutocompletion) {
setCursorLocation(previousCursorLocation);
}
}
}

View File

@@ -9,21 +9,46 @@ class App;
class PythonTextArea : public TextArea {
public:
enum class AutocompletionType : uint8_t {
EndOfIdentifier,
MiddleOfIdentifier,
NoIdentifier
};
PythonTextArea(Responder * parentResponder, App * pythonDelegate, const KDFont * font) :
TextArea(parentResponder, &m_contentView, font),
m_contentView(pythonDelegate, font)
m_contentView(pythonDelegate, font),
m_autocompletionResultIndex(0)
{
}
void loadSyntaxHighlighter() { m_contentView.loadSyntaxHighlighter(); }
void unloadSyntaxHighlighter() { m_contentView.unloadSyntaxHighlighter(); }
bool handleEvent(Ion::Events::Event event) override;
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
/* autocompletionType returns:
* - EndOfIdentifier if there is currently autocompletion, or if the cursor is
* at the end of an identifier,
* - MiddleOfIdentifier is the cursor is in the middle of an identifier,
* - No identifier otherwise.
* The autocompletionLocation can be provided with autocompletionLocation, or
* retreived with autocompletionLocationBeginning and autocompletionLocationEnd. */
AutocompletionType autocompletionType(const char * autocompletionLocation = nullptr, const char ** autocompletionLocationBeginning = nullptr, const char ** autocompletionLocationEnd = nullptr) const;
bool isAutocompleting() const { return m_contentView.isAutocompleting(); }
protected:
class ContentView : public TextArea::ContentView {
public:
ContentView(App * pythonDelegate, const KDFont * font) :
TextArea::ContentView(font),
m_pythonDelegate(pythonDelegate)
m_pythonDelegate(pythonDelegate),
m_autocomplete(false),
m_autocompletionEnd(nullptr)
{
}
App * pythonDelegate() { return m_pythonDelegate; }
void setAutocompleting(bool autocomplete) { m_autocomplete = autocomplete; }
bool isAutocompleting() const { return m_autocomplete; }
const char * autocompletionEnd() const { assert(m_autocomplete); return m_autocompletionEnd; }
void setAutocompletionEnd(const char * end) { m_autocompletionEnd = end; }
const char * textToAutocomplete() const;
void loadSyntaxHighlighter();
void unloadSyntaxHighlighter();
void clearRect(KDContext * ctx, KDRect rect) const override;
@@ -31,10 +56,19 @@ protected:
KDRect dirtyRectFromPosition(const char * position, bool includeFollowingLines) const override;
private:
App * m_pythonDelegate;
bool m_autocomplete;
const char * m_autocompletionEnd;
};
private:
void removeAutocompletion();
void removeAutocompletionText(); // Just removes the suggested text, not the autocompletion mode
void addAutocompletion();
bool addAutocompletionTextAtIndex(int nextIndex, int * currentIndexToUpdate = nullptr); // Assumes the var box is already loaded
void cycleAutocompletion(bool downwards);
void acceptAutocompletion(bool moveCursorToEndOfAutocompletion);
const ContentView * nonEditableContentView() const override { return &m_contentView; }
ContentView m_contentView;
int m_autocompletionResultIndex;
};
}

View File

@@ -120,7 +120,18 @@ const ToolboxMessageTree MatplotlibPyplotModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPlot, I18n::Message::PythonPlot),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandScatter, I18n::Message::PythonScatter),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandShow, I18n::Message::PythonShow),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandText, I18n::Message::PythonText)
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandText, I18n::Message::PythonText),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlue, I18n::Message::PythonColorBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorRed, I18n::Message::PythonColorRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorYellow, I18n::Message::PythonColorYellow, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBrown, I18n::Message::PythonColorBrown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlack, I18n::Message::PythonColorBlack, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorWhite, I18n::Message::PythonColorWhite, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorPink, I18n::Message::PythonColorPink, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorOrange, I18n::Message::PythonColorOrange, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorPurple, I18n::Message::PythonColorPurple, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGrey, I18n::Message::PythonColorGrey, false)
};
const ToolboxMessageTree TurtleModuleChildren[] = {
@@ -141,22 +152,23 @@ const ToolboxMessageTree TurtleModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPenup, I18n::Message::PythonTurtlePenup, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPensize, I18n::Message::PythonTurtlePensize),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandIsdown, I18n::Message::PythonTurtleIsdown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandWrite, I18n::Message::PythonTurtleWrite),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandReset, I18n::Message::PythonTurtleReset, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandShowturtle, I18n::Message::PythonTurtleShowturtle, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHideturtle, I18n::Message::PythonTurtleHideturtle, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColor, I18n::Message::PythonTurtleColor, false, I18n::Message::PythonTurtleCommandColorWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColor, I18n::Message::PythonTurtleColor),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBlue, I18n::Message::PythonTurtleBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandRed, I18n::Message::PythonTurtleRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGreen, I18n::Message::PythonTurtleGreen, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandYellow, I18n::Message::PythonTurtleYellow, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBrown, I18n::Message::PythonTurtleBrown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBlack, I18n::Message::PythonTurtleBlack, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandWhite, I18n::Message::PythonTurtleWhite, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPink, I18n::Message::PythonTurtlePink, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandOrange, I18n::Message::PythonTurtleOrange, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPurple, I18n::Message::PythonTurtlePurple, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGrey, I18n::Message::PythonTurtleGrey, false)
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlue, I18n::Message::PythonColorBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorRed, I18n::Message::PythonColorRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorYellow, I18n::Message::PythonColorYellow, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBrown, I18n::Message::PythonColorBrown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlack, I18n::Message::PythonColorBlack, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorWhite, I18n::Message::PythonColorWhite, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorPink, I18n::Message::PythonColorPink, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorOrange, I18n::Message::PythonColorOrange, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorPurple, I18n::Message::PythonColorPurple, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGrey, I18n::Message::PythonColorGrey, false)
};
const ToolboxMessageTree RandomModuleChildren[] = {
@@ -278,9 +290,9 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBackward, I18n::Message::PythonTurtleBackward),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBar, I18n::Message::PythonBar),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBin, I18n::Message::PythonBin),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBlack, I18n::Message::PythonTurtleBlack, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBlue, I18n::Message::PythonTurtleBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBrown, I18n::Message::PythonTurtleBrown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlack, I18n::Message::PythonColorBlack, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlue, I18n::Message::PythonColorBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBrown, I18n::Message::PythonColorBrown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCeil, I18n::Message::PythonCeil),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandChoice, I18n::Message::PythonChoice),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandCircle, I18n::Message::PythonTurtleCircle),
@@ -319,8 +331,8 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPixel, I18n::Message::PythonGetPixel),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetrandbits, I18n::Message::PythonGetrandbits),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGoto, I18n::Message::PythonTurtleGoto),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGreen, I18n::Message::PythonTurtleGreen, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGrey, I18n::Message::PythonTurtleGrey, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGrey, I18n::Message::PythonColorGrey, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGrid, I18n::Message::PythonGrid),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHeading, I18n::Message::PythonTurtleHeading, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandHex, I18n::Message::PythonHex),
@@ -366,19 +378,19 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandModf, I18n::Message::PythonModf),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandMonotonic, I18n::Message::PythonMonotonic, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandOct, I18n::Message::PythonOct),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandOrange, I18n::Message::PythonTurtleOrange, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorOrange, I18n::Message::PythonColorOrange, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPendown, I18n::Message::PythonTurtlePendown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPenup, I18n::Message::PythonTurtlePenup, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPensize, I18n::Message::PythonTurtlePensize),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPhase, I18n::Message::PythonPhase),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandConstantPi, I18n::Message::PythonConstantPi, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPink, I18n::Message::PythonTurtlePink, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorPink, I18n::Message::PythonColorPink, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPolar, I18n::Message::PythonPolar),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPosition, I18n::Message::PythonTurtlePosition, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPower, I18n::Message::PythonPower),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPlot, I18n::Message::PythonPlot),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPrint, I18n::Message::PythonPrint),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPurple, I18n::Message::PythonTurtlePurple, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorPurple, I18n::Message::PythonColorPurple, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRadians, I18n::Message::PythonRadians),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandint, I18n::Message::PythonRandint),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandom, I18n::Message::PythonRandom, false),
@@ -387,7 +399,7 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRangeStartStop, I18n::Message::PythonRangeStartStop),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRangeStop, I18n::Message::PythonRangeStop),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRect, I18n::Message::PythonRect),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandRed, I18n::Message::PythonTurtleRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorRed, I18n::Message::PythonColorRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandReset, I18n::Message::PythonTurtleReset, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandRight, I18n::Message::PythonTurtleRight),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRound, I18n::Message::PythonRound),
@@ -411,8 +423,9 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTrunc, I18n::Message::PythonTrunc),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTurtleFunction, I18n::Message::PythonTurtleFunction, false, I18n::Message::PythonCommandTurtleFunctionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUniform, I18n::Message::PythonUniform),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandWhite, I18n::Message::PythonTurtleWhite, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandYellow, I18n::Message::PythonTurtleYellow, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorWhite, I18n::Message::PythonColorWhite, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandWrite, I18n::Message::PythonTurtleWrite),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorYellow, I18n::Message::PythonColorYellow, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImag, I18n::Message::PythonImag, false, I18n::Message::PythonCommandImagWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandReal, I18n::Message::PythonReal, false, I18n::Message::PythonCommandRealWithoutArg)
};
@@ -465,6 +478,20 @@ PythonToolbox::PythonToolbox() :
{
}
const ToolboxMessageTree * PythonToolbox::moduleChildren(const char * name, int * numberOfNodes) const {
for (ToolboxMessageTree t : modulesChildren) {
if (strcmp(I18n::translate(t.label()), name) == 0) {
const int childrenCount = t.numberOfChildren();
if (numberOfNodes != nullptr) {
*numberOfNodes = childrenCount;
}
assert(childrenCount > 0);
return static_cast<const ToolboxMessageTree *>(t.childAtIndex(0));
}
}
return nullptr;
}
bool PythonToolbox::handleEvent(Ion::Events::Event event) {
if (Toolbox::handleEvent(event)) {
return true;
@@ -490,7 +517,7 @@ KDCoordinate PythonToolbox::rowHeight(int j) {
* We thus decided to compute the real height only for the ifStatement
* children of the toolbox, which is the only menu that has special height
* rows. */
const ToolboxMessageTree * messageTree = static_cast<const ToolboxMessageTree *>(m_messageTreeModel->children(j));
const ToolboxMessageTree * messageTree = static_cast<const ToolboxMessageTree *>(m_messageTreeModel->childAtIndex(j));
return k_font->stringSize(I18n::translate(messageTree->label())).height() + 2*Metric::TableCellVerticalMargin + (messageTree->text() == I18n::Message::Default ? 0 : Toolbox::rowHeight(j));
}
return Toolbox::rowHeight(j);
@@ -498,7 +525,7 @@ KDCoordinate PythonToolbox::rowHeight(int j) {
bool PythonToolbox::selectLeaf(int selectedRow) {
m_selectableTableView.deselectTable();
ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->children(selectedRow);
ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow);
const char * editedText = I18n::translate(node->insertedText());
// strippedEditedText array needs to be in the same scope as editedText
char strippedEditedText[k_maxMessageSize];
@@ -539,7 +566,7 @@ void PythonToolbox::scrollToLetter(char letter) {
char lowerLetter = tolower(letter);
int index = -1;
for (int i = 0; i < m_messageTreeModel->numberOfChildren(); i++) {
char l = tolower(I18n::translate(m_messageTreeModel->children(i)->label())[0]);
char l = tolower(I18n::translate(m_messageTreeModel->childAtIndex(i)->label())[0]);
if (l == lowerLetter) {
index = i;
break;

View File

@@ -10,7 +10,11 @@ namespace Code {
class PythonToolbox : public Toolbox {
public:
// PythonToolbox
PythonToolbox();
const ToolboxMessageTree * moduleChildren(const char * name, int * numberOfNodes) const;
// Toolbox
bool handleEvent(Ion::Events::Event event) override;
const ToolboxMessageTree * rootModel() const override;
protected:

View File

@@ -65,22 +65,54 @@ bool Script::nameCompliant(const char * name) {
return false;
}
bool Script::importationStatus() const {
assert(!isNull());
Data d = value();
return (((char *)d.buffer)[0] == 1);
uint8_t * StatusFromData(Script::Data d) {
return const_cast<uint8_t *>(static_cast<const uint8_t *>(d.buffer));
}
void Script::toggleImportationStatus() {
bool Script::autoImportationStatus() const {
return getStatutBit(k_autoImportationStatusMask);
}
void Script::toggleAutoimportationStatus() {
assert(!isNull());
Data d = value();
((char *)d.buffer)[0] = (((char *)d.buffer)[0] == 1 ? 0 : 1);
*StatusFromData(d) ^= k_autoImportationStatusMask;
setValue(d);
}
const char * Script::scriptContent() const {
const char * Script::content() const {
Data d = value();
return ((const char *)d.buffer) + StatusSize();
}
bool Script::fetchedFromConsole() const {
return getStatutBit(k_fetchedFromConsoleMask);
}
void Script::setFetchedFromConsole(bool fetched) {
setStatutBit(k_fetchedFromConsoleMask, k_fetchedFromConsoleOffset, fetched);
}
bool Script::fetchedForVariableBox() const {
return getStatutBit(k_fetchedForVariableBoxMask);
}
void Script::setFetchedForVariableBox(bool fetched) {
setStatutBit(k_fetchedForVariableBoxMask, k_fetchedForVariableBoxOffset, fetched);
}
bool Script::getStatutBit(uint8_t mask) const {
assert(!isNull());
Data d = value();
return (const char *)d.buffer + k_importationStatusSize;
return ((*StatusFromData(d)) & mask) != 0;
}
void Script::setStatutBit(uint8_t mask, uint8_t offset, bool statusBit) {
assert(!isNull());
Data d = value();
uint8_t * status = StatusFromData(d);
*status = ((*status) & ~mask) | (static_cast<uint8_t>(statusBit) << offset); //TODO Create and use a bit operations library
setValue(d);
}
}

View File

@@ -5,16 +5,36 @@
namespace Code {
/* Record : | Total Size | Name | Body |
* Script: | AutoImportationStatus | Content |*/
/* Record: | Size | Name | Body |
* Script: | | | Status | Content |
*
*
* |FetchedForVariableBoxBit
* Status is one byte long: xxxxxxxx
* ^ ^
* FetchedFromConsoleBit AutoImportationBit
*
* AutoImportationBit is 1 if the script should be auto imported when the
* console opens.
*
* FetchedFromConsoleBit is 1 if its content has been fetched from the console,
* so we can retrieve the correct variables afterwards in the variable box.
*
* FetchedForVariableBoxBit is used to prevent circular importation problems,
* such as scriptA importing scriptB, which imports scriptA. Once we get the
* variables from a script to put them in the variable box, we switch the bit to
* 1 and won't reload it afterwards. */
class Script : public Ion::Storage::Record {
private:
// Default script names are chosen between script1 and script99
static constexpr int k_maxNumberOfDefaultScriptNames = 99;
static constexpr int k_defaultScriptNameNumberMaxSize = 2; // Numbers from 1 to 99 have 2 digits max
// See the comment at the beginning of the file
static constexpr size_t k_statusSize = 1;
public:
static constexpr size_t k_importationStatusSize = 1;
static constexpr int k_defaultScriptNameMaxSize = 6 + k_defaultScriptNameNumberMaxSize + 1;
/* 6 = strlen("script")
* k_defaultScriptNameNumberMaxSize = maxLength of integers between 1 and 99
@@ -22,11 +42,29 @@ public:
static bool DefaultName(char buffer[], size_t bufferSize);
static bool nameCompliant(const char * name);
static constexpr size_t StatusSize() { return k_statusSize; }
Script(Ion::Storage::Record r) : Record(r) {}
bool importationStatus() const;
void toggleImportationStatus();
const char * scriptContent() const;
Script(Ion::Storage::Record r = Ion::Storage::Record()) : Record(r) {}
bool autoImportationStatus() const;
void toggleAutoimportationStatus();
const char * content() const;
/* Fetched status */
bool fetchedFromConsole() const;
void setFetchedFromConsole(bool fetched);
bool fetchedForVariableBox() const;
void setFetchedForVariableBox(bool fetched);
private:
static constexpr uint8_t k_autoImportationStatusMask = 0b1;
static constexpr uint8_t k_fetchedForVariableBoxOffset = 7;
static constexpr uint8_t k_fetchedFromConsoleOffset = 6;
static constexpr uint8_t k_fetchedForVariableBoxMask = 0b1 << k_fetchedForVariableBoxOffset;
static constexpr uint8_t k_fetchedFromConsoleMask = 0b1 << k_fetchedFromConsoleOffset;
bool getStatutBit(uint8_t offset) const;
void setStatutBit(uint8_t mask, uint8_t offset, bool value);
};
}

View File

@@ -1,33 +1,35 @@
#ifndef CODE_SCRIPT_NODE_H
#define CODE_SCRIPT_NODE_H
#include <stddef.h>
#include <stdint.h>
namespace Code {
class ScriptNode {
public:
enum class Type {
Function = 0,
Variable = 1
enum class Type : bool {
WithoutParentheses,
WithParentheses
};
ScriptNode() :
m_type(Type::Function), m_name(nullptr), m_scriptIndex(0) {}
static ScriptNode FunctionNode(const char * name, uint16_t scriptIndex) {
return ScriptNode(Type::Function, name, scriptIndex);
}
static ScriptNode VariableNode(const char * name, uint16_t scriptIndex) {
return ScriptNode(Type::Variable, name, scriptIndex);
}
ScriptNode(Type type = Type::WithoutParentheses, const char * name = nullptr, int nameLength = -1, const char * nodeSourceName = nullptr, const char * description = nullptr) :
m_type(type),
m_name(name),
m_nodeSourceName(nodeSourceName),
m_description(description),
m_nameLength(nameLength)
{}
Type type() const { return m_type; }
const char * name() const { return m_name; }
uint16_t scriptIndex() const { return m_scriptIndex; }
int nameLength() const { return static_cast<int>(m_nameLength); }
const char * nodeSourceName() const { return m_nodeSourceName; }
const char * description() const { return m_description; }
private:
ScriptNode(Type type, const char * name, uint16_t scriptIndex) :
m_type(type), m_name(name), m_scriptIndex(scriptIndex) {}
Type m_type;
const char * m_name;
uint16_t m_scriptIndex;
const char * m_nodeSourceName;
const char * m_description;
size_t m_nameLength;
};
}

View File

@@ -7,47 +7,51 @@ namespace Code {
constexpr char ScriptNodeCell::k_parentheses[];
constexpr char ScriptNodeCell::k_parenthesesWithEmpty[];
ScriptNodeCell::ScriptNodeView::ScriptNodeView() :
HighlightCell(),
m_scriptNode(nullptr),
m_scriptStore(nullptr)
{
}
void ScriptNodeCell::ScriptNodeView::setScriptNode(ScriptNode * scriptNode) {
m_scriptNode = scriptNode;
}
void ScriptNodeCell::ScriptNodeView::setScriptStore(ScriptStore * scriptStore) {
m_scriptStore = scriptStore;
}
void ScriptNodeCell::ScriptNodeView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->drawString(m_scriptNode->name(), KDPoint(0, Metric::TableCellVerticalMargin), k_font, Palette::CodeText, isHighlighted()? Palette::CodeBackgroundSelected : Palette::CodeBackground);
KDSize nameSize = k_font->stringSize(m_scriptNode->name());
if (m_scriptNode->type() == ScriptNode::Type::Function) {
ctx->drawString(ScriptNodeCell::k_parentheses, KDPoint(nameSize.width(), Metric::TableCellVerticalMargin), k_font, Palette::CodeText, isHighlighted()? Palette::CodeBackgroundSelected : Palette::CodeBackground);
const KDColor backgroundColor = isHighlighted()? Palette::CodeBackgroundSelected : Palette::CodeBackground;
// If it exists, draw the description name.
const char * descriptionName = m_scriptNode->description();
if (descriptionName != nullptr) {
ctx->drawString(descriptionName, KDPoint(0, m_frame.height() - k_bottomMargin - k_font->glyphSize().height()), k_font, Palette::GreyDark, backgroundColor);
}
// Draw the node name
const char * nodeName = m_scriptNode->name();
const int nodeNameLength = m_scriptNode->nameLength();
KDSize nameSize = k_font->stringSize(nodeName, nodeNameLength);
const KDCoordinate nodeNameY = k_topMargin;
ctx->drawString(nodeName, KDPoint(0, nodeNameY), k_font, KDColorBlack, backgroundColor, nodeNameLength);
// If it is needed, draw the parentheses
if (m_scriptNode->type() == ScriptNode::Type::WithParentheses) {
ctx->drawString(ScriptNodeCell::k_parentheses, KDPoint(nameSize.width(), nodeNameY), k_font, KDColorBlack, backgroundColor);
}
/* If it exists, draw the source name. If it did not fit, we would have put
* nullptr at the node creation. */
const char * sourceName = m_scriptNode->nodeSourceName();
if (sourceName != nullptr) {
KDSize sourceNameSize = k_font->stringSize(sourceName);
ctx->drawString(sourceName, KDPoint(m_frame.width() - sourceNameSize.width(), nodeNameY), k_font, Palette::CodeText, backgroundColor);
}
ctx->drawString(m_scriptStore->scriptAtIndex(m_scriptNode->scriptIndex()).fullName(), KDPoint(0, Metric::TableCellVerticalMargin + nameSize.height() + k_verticalMargin), k_font, Palette::SecondaryText, isHighlighted()? Palette::CodeBackgroundSelected : Palette::CodeBackground);
}
KDSize ScriptNodeCell::ScriptNodeView::minimalSizeForOptimalDisplay() const {
if (m_scriptNode->name() == nullptr) {
return KDSizeZero;
}
KDSize size1 = k_font->stringSize(m_scriptNode->name());
KDSize size2 = k_font->stringSize(m_scriptStore->scriptAtIndex(m_scriptNode->scriptIndex()).fullName());
KDSize size3 = KDSizeZero;
if (m_scriptNode->type() == ScriptNode::Type::Function) {
size3 = k_font->stringSize(ScriptNodeCell::k_parentheses);
}
return KDSize(size1.width() + size3.width() > size2.width() ? size1.width() + size3.width() : size2.width(), Metric::TableCellVerticalMargin + size1.width() + k_verticalMargin + size2.width());
return KDSize(
k_optimalWidth,
m_scriptNode->description() == nullptr ? k_simpleItemHeight : k_complexItemHeight);
}
ScriptNodeCell::ScriptNodeCell() :
TableCell(),
m_scriptNodeView()
{
bool ScriptNodeCell::CanDisplayNameAndSource(int nameLength, const char * source) {
if (source == nullptr) {
return true;
}
assert(nameLength > 0);
const KDFont * font = ScriptNodeView::k_font;
return font->glyphSize().width()*(nameLength + 1) + font->stringSize(source).width() <= ScriptNodeView::k_optimalWidth; // + 1 for the separating space
}
void ScriptNodeCell::setScriptNode(ScriptNode * scriptNode) {
@@ -55,10 +59,6 @@ void ScriptNodeCell::setScriptNode(ScriptNode * scriptNode) {
reloadCell();
}
void ScriptNodeCell::setScriptStore(ScriptStore * scriptStore) {
m_scriptNodeView.setScriptStore(scriptStore);
}
void ScriptNodeCell::setHighlighted(bool highlight) {
TableCell::setHighlighted(highlight);
m_scriptNodeView.setHighlighted(highlight);

View File

@@ -10,9 +10,18 @@ namespace Code {
class ScriptNodeCell : public TableCell {
public:
ScriptNodeCell();
static_assert('\x11' == UCodePointEmpty, "Unicode error");
constexpr static char k_parentheses[] = "()";
constexpr static char k_parenthesesWithEmpty[] = "(\x11)";
constexpr static KDCoordinate k_simpleItemHeight = 27;
constexpr static KDCoordinate k_complexItemHeight = 42;
ScriptNodeCell() :
TableCell(),
m_scriptNodeView()
{}
void setScriptNode(ScriptNode * node);
void setScriptStore(ScriptStore * scriptStore);
static bool CanDisplayNameAndSource(int nameLength, const char * source);
/* TableCell */
View * labelView() const override { return const_cast<View *>(static_cast<const View *>(&m_scriptNodeView)); }
@@ -22,26 +31,25 @@ public:
void reloadCell() override;
const char * text() const override { return m_scriptNodeView.text(); }
static_assert('\x11' == UCodePointEmpty, "Unicode error");
constexpr static char k_parentheses[] = "()";
constexpr static char k_parenthesesWithEmpty[] = "(\x11)";
protected:
class ScriptNodeView : public HighlightCell {
public:
ScriptNodeView();
void setScriptNode(ScriptNode * scriptNode);
void setScriptStore(ScriptStore * scriptStore);
constexpr static const KDFont * k_font = KDFont::SmallFont;
constexpr static KDCoordinate k_optimalWidth = Ion::Display::Width - Metric::PopUpLeftMargin - Metric::PopUpRightMargin;
ScriptNodeView() :
HighlightCell(),
m_scriptNode(nullptr)
{}
void setScriptNode(ScriptNode * node) { m_scriptNode = node; }
void drawRect(KDContext * ctx, KDRect rect) const override;
virtual KDSize minimalSizeForOptimalDisplay() const override;
const char * text() const override {
return m_scriptStore->scriptAtIndex(m_scriptNode->scriptIndex()).fullName();
return m_scriptNode->description();
}
private:
constexpr static const KDFont * k_font = KDFont::SmallFont;
constexpr static KDCoordinate k_verticalMargin = 7;
constexpr static KDCoordinate k_bottomMargin = 5;
constexpr static KDCoordinate k_topMargin = k_bottomMargin + k_separatorThickness;
ScriptNode * m_scriptNode;
ScriptStore * m_scriptStore;
};
ScriptNodeView m_scriptNodeView;
};

View File

@@ -45,7 +45,7 @@ bool ScriptParameterController::handleEvent(Ion::Events::Event event) {
m_menuController->renameSelectedScript();
return true;
case 2:
m_script.toggleImportationStatus();
m_script.toggleAutoimportationStatus();
m_selectableTableView.reloadData();
m_menuController->reloadConsole();
Container::activeApp()->setFirstResponder(&m_selectableTableView);
@@ -95,7 +95,7 @@ HighlightCell * ScriptParameterController::reusableCell(int index) {
void ScriptParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) {
if (cell == &m_autoImportScript) {
SwitchView * switchView = (SwitchView *)m_autoImportScript.accessoryView();
switchView->setState(m_script.importationStatus());
switchView->setState(m_script.autoImportationStatus());
} else if (cell == &m_size) {
MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell;
GetScriptSize(myCell);

View File

@@ -1,23 +1,14 @@
#include "script_store.h"
#include "string.h"
#include <stddef.h>
extern "C" {
#include "py/lexer.h"
#include "py/nlr.h"
}
namespace Code {
constexpr char ScriptStore::k_scriptExtension[];
bool ScriptStore::ScriptNameIsFree(const char * baseName) {
return Ion::Storage::sharedStorage()->recordBaseNamedWithExtension(baseName, k_scriptExtension).isNull();
return ScriptBaseNamed(baseName).isNull();
}
ScriptStore::ScriptStore()
{
ScriptStore::ScriptStore() {
addScriptFromTemplate(ScriptTemplate::Squares());
addScriptFromTemplate(ScriptTemplate::Parabola());
addScriptFromTemplate(ScriptTemplate::Mandelbrot());
@@ -34,124 +25,39 @@ bool ScriptStore::isFull() {
return Ion::Storage::sharedStorage()->availableSize() < k_fullFreeSpaceSizeLimit;
}
void ScriptStore::scanScriptsForFunctionsAndVariables(void * context, ScanCallback storeFunction, ScanCallback storeVariable) {
for (int scriptIndex = 0; scriptIndex < numberOfScripts(); scriptIndex++) {
//Don't scan not loaded script
if (!scriptAtIndex(scriptIndex).importationStatus()){
continue;
}
// Handle lexer or parser errors with nlr.
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
const char * scriptContent = scriptAtIndex(scriptIndex).scriptContent();
if (scriptContent == nullptr) {
continue;
}
mp_lexer_t *lex = mp_lexer_new_from_str_len(0, scriptContent, strlen(scriptContent), false);
mp_parse_tree_t parseTree = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_parse_node_t pn = parseTree.root;
if (!MP_PARSE_NODE_IS_STRUCT(pn)) {
mp_parse_tree_clear(&parseTree);
nlr_pop();
continue;
}
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
// The script is only a single function definition.
if (((uint)(MP_PARSE_NODE_STRUCT_KIND(pns))) == k_functionDefinitionParseNodeStructKind) {
const char * id = structID(pns);
if (id == nullptr) {
continue;
}
storeFunction(context, id, scriptIndex);
mp_parse_tree_clear(&parseTree);
nlr_pop();
continue;
}
// The script is only a single global variable definition.
if (((uint)(MP_PARSE_NODE_STRUCT_KIND(pns))) == k_expressionStatementParseNodeStructKind) {
const char * id = structID(pns);
if (id == nullptr) {
continue;
}
storeVariable(context, id, scriptIndex);
mp_parse_tree_clear(&parseTree);
nlr_pop();
continue;
}
if (((uint)(MP_PARSE_NODE_STRUCT_KIND(pns))) != k_fileInput2ParseNodeStructKind) {
// The script node is not of type "file_input_2", thus it will not have main
// structures of the wanted type.
mp_parse_tree_clear(&parseTree);
nlr_pop();
continue;
}
// Count the number of structs in child nodes.
size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
for (size_t i = 0; i < n; i++) {
mp_parse_node_t child = pns->nodes[i];
if (MP_PARSE_NODE_IS_STRUCT(child)) {
mp_parse_node_struct_t *child_pns = (mp_parse_node_struct_t*)(child);
if (((uint)(MP_PARSE_NODE_STRUCT_KIND(child_pns))) == k_functionDefinitionParseNodeStructKind) {
const char * id = structID(child_pns);
if (id == nullptr) {
continue;
}
storeFunction(context, id, scriptIndex);
} else if (((uint)(MP_PARSE_NODE_STRUCT_KIND(child_pns))) == k_expressionStatementParseNodeStructKind) {
const char * id = structID(child_pns);
if (id == nullptr) {
continue;
}
storeVariable(context, id, scriptIndex);
}
}
}
mp_parse_tree_clear(&parseTree);
nlr_pop();
}
}
}
const char * ScriptStore::contentOfScript(const char * name) {
Script script = scriptNamed(name);
const char * ScriptStore::contentOfScript(const char * name, bool markAsFetched) {
Script script = ScriptNamed(name);
if (script.isNull()) {
return nullptr;
}
return script.scriptContent();
if (markAsFetched) {
script.setFetchedFromConsole(true);
}
return script.content();
}
void ScriptStore::clearVariableBoxFetchInformation() {
// TODO optimize fetches
const int scriptsCount = numberOfScripts();
for (int i = 0; i < scriptsCount; i++) {
scriptAtIndex(i).setFetchedForVariableBox(false);
}
}
void ScriptStore::clearConsoleFetchInformation() {
// TODO optimize fetches
const int scriptsCount = numberOfScripts();
for (int i = 0; i < scriptsCount; i++) {
scriptAtIndex(i).setFetchedFromConsole(false);
}
}
Script::ErrorStatus ScriptStore::addScriptFromTemplate(const ScriptTemplate * scriptTemplate) {
size_t valueSize = strlen(scriptTemplate->content())+1+1;// scriptcontent size + 1 char for the importation status
size_t valueSize = Script::StatusSize() + strlen(scriptTemplate->content()) + 1; // (auto importation status + content fetched status) + scriptcontent size + null-terminating char
assert(Script::nameCompliant(scriptTemplate->name()));
Script::ErrorStatus err = Ion::Storage::sharedStorage()->createRecordWithFullName(scriptTemplate->name(), scriptTemplate->value(), valueSize);
assert(err != Script::ErrorStatus::NonCompliantName);
return err;
}
const char * ScriptStore::structID(mp_parse_node_struct_t *structNode) {
// Find the id child node, which stores the struct's name
size_t childNodesCount = MP_PARSE_NODE_STRUCT_NUM_NODES(structNode);
if (childNodesCount < 1) {
return nullptr;
}
mp_parse_node_t child = structNode->nodes[0];
if (MP_PARSE_NODE_IS_LEAF(child)
&& MP_PARSE_NODE_LEAF_KIND(child) == MP_PARSE_NODE_ID)
{
uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(child);
return qstr_str(arg);
}
return nullptr;
}
}

View File

@@ -23,8 +23,11 @@ public:
Script scriptAtIndex(int index) {
return Script(Ion::Storage::sharedStorage()->recordWithExtensionAtIndex(k_scriptExtension, index));
}
Script scriptNamed(const char * name) {
return Script(Ion::Storage::sharedStorage()->recordNamed(name));
static Script ScriptNamed(const char * fullName) {
return Script(Ion::Storage::sharedStorage()->recordNamed(fullName));
}
static Script ScriptBaseNamed(const char * baseName) {
return Script(Ion::Storage::sharedStorage()->recordBaseNamedWithExtension(baseName, k_scriptExtension));
}
int numberOfScripts() {
return Ion::Storage::sharedStorage()->numberOfRecordsWithExtension(k_scriptExtension);
@@ -35,12 +38,10 @@ public:
void deleteAllScripts();
bool isFull();
/* Provide scripts content information */
typedef void (* ScanCallback)(void * context, const char * p, int n);
void scanScriptsForFunctionsAndVariables(void * context, ScanCallback storeFunction,ScanCallback storeVariable);
/* MicroPython::ScriptProvider */
const char * contentOfScript(const char * name) override;
const char * contentOfScript(const char * name, bool markAsFetched) override;
void clearVariableBoxFetchInformation();
void clearConsoleFetchInformation();
Ion::Storage::Record::ErrorStatus addScriptFromTemplate(const ScriptTemplate * scriptTemplate);
private:
@@ -51,10 +52,6 @@ private:
* importation status (1 char), the default content "from math import *\n"
* (20 char) and 10 char of free space. */
static constexpr int k_fullFreeSpaceSizeLimit = sizeof(Ion::Storage::record_size_t)+Script::k_defaultScriptNameMaxSize+k_scriptExtensionLength+1+20+10;
static constexpr size_t k_fileInput2ParseNodeStructKind = 1;
static constexpr size_t k_functionDefinitionParseNodeStructKind = 3;
static constexpr size_t k_expressionStatementParseNodeStructKind = 5;
const char * structID(mp_parse_node_struct_t *structNode);
};
}

View File

@@ -1,6 +1,8 @@
#ifndef CODE_SCRIPT_TEMPLATE_H
#define CODE_SCRIPT_TEMPLATE_H
#include "script.h"
namespace Code {
class ScriptTemplate {
@@ -12,11 +14,11 @@ public:
static const ScriptTemplate * Polynomial();
static const ScriptTemplate * Parabola();
const char * name() const { return m_name; }
const char * content() const { return m_value+1; }
const char * content() const { return m_value + Script::StatusSize(); }
const char * value() const { return m_value; }
private:
const char * m_name;
const char * m_value; // hold the 'importation status' flag concatenate with the script content
const char * m_value; // holds the 'importation status' and 'current importation status' flags concatenated with the script content
};
}

View File

@@ -0,0 +1,70 @@
#include <quiz.h>
#include "../script_store.h"
#include "../variable_box_controller.h"
#include <string.h>
using namespace Code;
void assert_variables_are(const char * script, const char * nameToComplete, const char * * expectedVariables, int expectedVariablesCount) {
// Clean the store
ScriptStore store;
store.deleteAllScripts();
// Add the script
store.addNewScript();
constexpr int dataBufferSize = 500;
char dataBuffer[dataBufferSize];
Ion::Storage::Record::Data data = {
.buffer = &dataBuffer,
.size = dataBufferSize
};
strlcpy(dataBuffer, script, dataBufferSize);
constexpr int scriptIndex = 0;
store.scriptAtIndex(scriptIndex).setValue(data);
// Load the variable box
VariableBoxController varBox(&store);
const size_t nameToCompleteLength = strlen(nameToComplete);
varBox.loadFunctionsAndVariables(scriptIndex, nameToComplete, nameToCompleteLength);
// Compare the variables
int index = 0; // Index to make sure we are not cycling through the results
int textToInsertLength;
bool addParentheses;
for (int i = 0; i < expectedVariablesCount; i++) {
quiz_assert(i == index);
const char * autocompletionI = varBox.autocompletionAlternativeAtIndex(
nameToCompleteLength,
&textToInsertLength,
&addParentheses,
i,
&index);
quiz_assert(i == index); // If false, the autompletion has cycled: there are not as many results as expected
quiz_assert(strncmp(*(expectedVariables + i), autocompletionI - nameToCompleteLength, textToInsertLength + nameToCompleteLength) == 0);
index++;
}
varBox.autocompletionAlternativeAtIndex(
strlen(nameToComplete),
&textToInsertLength,
&addParentheses,
index,
&index);
/* Assert the autocompletion has cycles: otherwise, there are more results
* than expected. */
quiz_assert(index == 0);
}
QUIZ_CASE(variable_box_controller) {
const char * expectedVariables[] = {
"froo",
"from",
"frozenset()"
};
// FIXME This test does not load imported variables for now
assert_variables_are(
"\x01 from math import *\nfroo=3",
"fr",
expectedVariables,
sizeof(expectedVariables) / sizeof(const char *));
}

View File

@@ -0,0 +1,4 @@
Functions = "Funzioni"
Catalog = "Catalogo"
Modules = "Moduli"
LoopsAndTests = "Loops e test"

View File

@@ -0,0 +1,4 @@
Functions = "Functies"
Catalog = "Catalogus"
Modules = "Modules"
LoopsAndTests = "Loops and tests"

View File

@@ -1,6 +1,6 @@
Functions = "Functions"
Catalog = "Catalog"
Modules = "Modules"
LoopsAndTests = "Loops and tests"
Functions = "Funções"
Catalog = "Catálogo"
Modules = "Módulos"
LoopsAndTests = "Laços e testes"
Files = "Files"
Exceptions = "Exceptions"

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,17 @@
#ifndef CODE_VARIABLE_BOX_CONTROLLER_H
#define CODE_VARIABLE_BOX_CONTROLLER_H
#include <escher.h>
#include <apps/alternate_empty_nested_menu_controller.h>
#include <escher/message_table_cell.h>
#include <escher/toolbox_message_tree.h>
#include "script_node.h"
#include "script_node_cell.h"
#include "script_store.h"
#include "variable_box_empty_controller.h"
namespace Code {
class VariableBoxController : public NestedMenuController {
class VariableBoxController : public AlternateEmptyNestedMenuController {
public:
VariableBoxController(ScriptStore * scriptStore);
@@ -16,28 +19,98 @@ public:
bool handleEvent(Ion::Events::Event event) override;
void didEnterResponderChain(Responder * previousFirstResponder) override;
/* ListViewDataSource */
/* TableViewDataSource */
KDCoordinate rowHeight(int j) override;
int numberOfRows() const override;
HighlightCell * reusableCell(int index, int type) override;
int reusableCellCount(int type) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
int typeAtLocation(int i, int j) override;
/* ListViewDataSource */
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
/* SelectableTableViewDelegate */
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override;
//AlternateEmptyNestedMenuController
ViewController * emptyViewController() override { return &m_variableBoxEmptyController; }
/* VariableBoxController */
void loadFunctionsAndVariables();
void setDisplaySubtitles(bool display) { m_displaySubtitles = display; }
void loadFunctionsAndVariables(int scriptIndex, const char * textToAutocomplete, int textToAutocompleteLength);
const char * autocompletionAlternativeAtIndex(int textToAutocompleteLength, int * textToInsertLength, bool * addParentheses, int index, int * indexToUpdate = nullptr);
void loadVariablesImportedFromScripts();
void empty();
void insertAutocompletionResultAtIndex(int index);
private:
constexpr static int k_maxScriptObjectNameSize = 100;
constexpr static int k_maxNumberOfDisplayedRows = 6; //240/40
constexpr static int k_maxScriptNodesCount = 32;
HighlightCell * leafCellAtIndex(int index) override;
HighlightCell * nodeCellAtIndex(int index) override { return nullptr; }
constexpr static size_t k_maxNumberOfDisplayedItems = (Ion::Display::Height - Metric::TitleBarHeight - Metric::PopUpTopMargin) / ScriptNodeCell::k_simpleItemHeight + 2; // +2 if the cells are cropped on top and at the bottom
constexpr static size_t k_maxScriptNodesCount = 32; // Chosen without particular reasons
constexpr static int k_totalBuiltinNodesCount = 107;
constexpr static uint8_t k_scriptOriginsCount = 3;
constexpr static uint8_t k_subtitleCellType = NodeCellType; // We don't care as it is not selectable
constexpr static uint8_t k_itemCellType = LeafCellType; // So that upper class NestedMenuController knows it's a leaf
constexpr static KDCoordinate k_subtitleRowHeight = 23;
enum class NodeOrigin : uint8_t {
CurrentScript = 0,
Builtins = 1,
Importation = 2
};
/* Returns:
* - a negative int if the node name is before name in alphabetical
* order
* - 0 if they are equal
* - a positive int if it is after in alphabetical order.
* strictlyStartsWith is set to True if the node name starts with name but
* they are not equal.*/
static int NodeNameCompare(ScriptNode * node, const char * name, int nameLength, bool * strictlyStartsWith = nullptr);
// Nodes and nodes count
static size_t MaxNodesCountForOrigin(NodeOrigin origin) {
return origin == NodeOrigin::Builtins ? k_totalBuiltinNodesCount : k_maxScriptNodesCount;
}
int nodesCountForOrigin(NodeOrigin origin) const;
size_t * nodesCountPointerForOrigin(NodeOrigin origin);
ScriptNode * nodesForOrigin(NodeOrigin origin);
ScriptNode * scriptNodeAtIndex(int index);
// Cell getters
int typeAndOriginAtLocation(int i, NodeOrigin * resultOrigin = nullptr, int * cumulatedOriginsCount = nullptr) const;
// NestedMenuController
HighlightCell * leafCellAtIndex(int index) override { assert(false); return nullptr; }
HighlightCell * nodeCellAtIndex(int index) override { assert(false); return nullptr; }
bool selectLeaf(int rowIndex) override;
void insertTextInCaller(const char * text);
void addFunctionAtIndex(const char * functionName, int scriptIndex);
void addVariableAtIndex(const char * variableName, int scriptIndex);
ScriptNode m_scriptNodes[k_maxScriptNodesCount];
int m_scriptNodesCount;
void insertTextInCaller(const char * text, int textLength = -1);
// Loading
void loadBuiltinNodes(const char * textToAutocomplete, int textToAutocompleteLength);
void loadImportedVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength);
void loadCurrentVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength);
void loadGlobalAndImportedVariablesInScriptAsImported(Script script, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true);
// Returns true if this was an import structure
bool addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true);
const char * importationSourceNameFromNode(mp_parse_node_t & node);
bool importationSourceIsModule(const char * sourceName, const ToolboxMessageTree * * moduleChildren = nullptr, int * numberOfModuleChildren = nullptr);
bool importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retreivedScript = nullptr);
bool addImportStructFromScript(mp_parse_node_struct_t * pns, uint structKind, const char * scriptName, const char * textToAutocomplete, int textToAutocompleteLength);
/* Add a node if it completes the text to autocomplete and if it is not
* already contained in the variable box. The returned boolean means we
* should escape the node scanning process (due to the lexicographical order
* or full node table). */
bool addNodeIfMatches(const char * textToAutocomplete, int textToAutocompleteLength, ScriptNode::Type type, NodeOrigin origin, const char * nodeName, int nodeNameLength = -1, const char * nodeSourceName = nullptr, const char * description = nullptr);
VariableBoxEmptyController m_variableBoxEmptyController;
ScriptNode m_currentScriptNodes[k_maxScriptNodesCount];
ScriptNode m_builtinNodes[k_totalBuiltinNodesCount];
ScriptNode m_importedNodes[k_maxScriptNodesCount];
ScriptNodeCell m_itemCells[k_maxNumberOfDisplayedItems];
MessageTableCell m_subtitleCells[k_scriptOriginsCount];
ScriptStore * m_scriptStore;
ScriptNodeCell m_leafCells[k_maxNumberOfDisplayedRows];
size_t m_currentScriptNodesCount;
size_t m_builtinNodesCount;
size_t m_importedNodesCount;
int m_shortenResultCharCount; // This is used to send only the completing text when we are autocompleting
bool m_displaySubtitles;
};
}

View File

@@ -0,0 +1,13 @@
#include "variable_box_empty_controller.h"
#include <apps/i18n.h>
namespace Code {
VariableBoxEmptyController::VariableBoxEmptyView::VariableBoxEmptyView() :
::ModalViewEmptyController::ModalViewEmptyView()
{
initMessageViews();
m_message.setMessage(I18n::Message::NoWordAvailableHere);
}
}

View File

@@ -0,0 +1,34 @@
#ifndef APPS_CODE_VARIABLE_BOX_EMPTY_CONTROLLER_H
#define APPS_CODE_VARIABLE_BOX_EMPTY_CONTROLLER_H
#include <escher/modal_view_empty_controller.h>
namespace Code {
class VariableBoxEmptyController : public ModalViewEmptyController {
public:
VariableBoxEmptyController() :
ModalViewEmptyController(),
m_view()
{}
// View Controller
View * view() override { return &m_view; }
private:
class VariableBoxEmptyView : public ModalViewEmptyController::ModalViewEmptyView {
public:
constexpr static int k_numberOfMessages = 1;
VariableBoxEmptyView();
private:
int numberOfMessageTextViews() const override { return k_numberOfMessages; }
MessageTextView * messageTextViewAtIndex(int index) override {
assert(index >= 0 && index < k_numberOfMessages);
return &m_message;
}
MessageTextView m_message;
};
VariableBoxEmptyView m_view;
};
}
#endif