# Scripting and macros in GeoGebra with comma expresion

gd shared this idea 13 years ago
Completed

GeoGebra is a program with great features but sometimes people would like to use it in a way which is not (yet) supported; they would often need features which are specific to special use cases and thus it would be irrational to include all of them in GeoGebra. This often leads to suboptimal workarounds with outlandish uses of animation or other features. The other option is to use worksheets and JavaScript but it restricts its use to applets which is inconvenient to use for creating constructions.

A solution, proposed by some people, would be to integrate a JavaScript interpreter into GeoGebra. GeoGebra already has a command language, so instead of that, here I try to propose a set of enhancements which would make it possible to immensely extend GeoGebra's capabilities without a completely different language. The features I suggest would help both the more advanced users to implement specific features they need and the development of complex toolkits for elliptic and hyperbolic geometry, mechanics simulations or even 3D geometry.

This and the related feature requests contain the ideas of Kalló Bernát (cie) and me (Grósz Dániel). They are the best we could of; it is possible that things can be done in a simpler way which we missed. He suggests that a Java plug-in interface could be made and it would be better to create complex toolkits in Java. He will probably write a request about that, which is technically unrelated. (He is attending at the GeoGebra conference.)

Comma expression

My idea is that the integration of a "scripting" feature would require the less architectural changes and it would fit together the best with GeoGebra's current features if everything could be done with expressions. The separation of the instructions should be done with an operator similar to the comma expression: an operator which evaluates both of its argument and returns the second, or practically which evaluates all the elements of a list in order and returns the last.

We already have this with Last[{expr1, expr2, ... , exprLast}] . If we want to use this for "scripting", a simpler syntax would be nice - unfortunately "," and ";" are already used for other purposes. Perhaps it could be {expr1; expr2; ... ; exprLast} .

Everything be an expression

To make "scripting" possible by this, we need to make it possible to use everything which is currently a command and not an expression as an expression which returns undefined. This includes the assignment operator and the Delete command.

Control structures

We already have conditionals. We practically have for loops too with Sequence. I propose a For command with the only substantial difference that it returns undefined so the calculated expressions do not need to be kept in the memory and with the expression parameter being the last to match the practice of other programming languages better. A foreach-like variant of both Sequence and For would be nice which, instead of min and max, take a list whose elements the loop variable would assume. The while loop could have the form While[condition, expression] which returns undefined too.

Copy by value (instead of every assignment creating a dependent object) would be necessary for most scripts (e. g. calculating something with a loop) to make sense. I post it in an other topic because it would be useful irrespectively of the scripting too.

Macros

In my conception macros would be a new object type, with similar uses to tools. They can have parameters and an expression (often a comma expression) of the parameters which is evaluated when the macro is executed. They can have a return value if they assign a value to the special object "result". The parameters have two properties: their type and whether they accept an existing object or a value. E. g. if a tool has an existing point parameter P and its expression is result=-P , then the user, when executing the macro, would have to click on a point, and the macro would mirror it to the origin, creating a dependent point. If the parameter is instead a point value, the user can click anywhere on the drawing pad (without creating a point there), and the macro would create a new free point with the initial position being the place where the user clicked mirrored to the origin.

A special type of parameters could be the PointOnCurve which is useful for creating semi-dependent objects, requires the user to click on a line, circle, etc., and it passes the two-element list of the curve and the place where it was clicked and it passes to the macro the two-element list of the curve as and existing object and the place of the click as a point value.

Macros, similarly to text objects, would no show up in the algebra window but they could be edited in the Properties dialog. The editor would be multi-line to allow a nicer formatting of scripts than a single line, with newlines interpreted as whitespace. The expression in the macro is only stored, not at all evaluated when the user edits the macro, so copy by value expressions are evaluated when executing a macro and not when creating it.

Macros could be exported to ggt files similarly to tools.

The uses of macros

The principal difference between tools and macros is that a macro is evaluated only when the user (or a listener) executes it and it never becomes part of the definition of an object.

The user would use a macro without a result in the following ways:

• Macros could have toolbar buttons like tools. When the user clicks on the button, GeoGebra asks for the parameters in the same way and then execute the macro; it would immediately execute the macro if it does not have parameters. They would not create an automatically named new object.
• They could be used as commands in the input line, like tools, which do not create an automatically named new object.
• When used in an expression, the interpreter would execute them and replace them with an undefined value.
• They could be used a listeners (see below).

The user would use a macro with a result in the following ways:

• With a toolbar button. The definition of the "result" object of the macro would be stored in an automatically named new object.
• As commands in the input line, creating an automatically named new object (similarly to tools).
• When the interpreter encounters a macro call in an expression (e. g. on the right side of an assignment) it would execute it and replace it with the definition of the "result" object.

I propose that macros be a type of object so that they can be easily edited in the properties window and (more importantly) they can be referred to by their name in listeners.

New commands

For macros to be fully functional I propose to make it possible to read and write the properties of the objects, similarly to the JavaScript interface. More specifically I propose to make available in GeoGebra the get and set commands for the following parameters: Color, Visible, LabelVisible, Trace, LineStyle, Thickness, PointStyle, PointSize, Filling, Animation, AnimSpeed, AnimDir, Fixed, Layer and the proposed property Class, and a setCoords command to move semi-dependent objects. Condition to show object and dynamic colors would be created by passing an expression to SetVisible and SetColor; copy by value could be used to set them statically to the value of an expression.

Object[] creating regular dependent object

I propose that when the interpreter encounters an Object command with a literal string parameter or a parameter which is immediately evaluated (with copy by value), it create a regular dependent object. Sometimes the name of an object would be stored as a reference to it and macros would use it like Object[%objName] . Currently the drawback of this is that if the object referred to by the value of objName is renamed, the definition is not changed accordingly. If Object["obj"] in a definition was changed by the interpreter to a dependency on obj, this drawback would be eliminated.

Element[] and Object[] returning full-fledged objects

When several objects are created automatically, it is usually best to organize them into a list instead of creating a number of automatically named objects. This way they do not waste the common namespace and the space in the algebra window and they can be operated (deleted, renamed) together. This has the drawback that list elements are only values, they cannot have different colors, animation speeds etc. I propose that they be full-fledged objects complete with the properties of normal objects and that Element[] and Object[] return objects that can be used in commands which expect existing objects and which can be assigned to ("lvalues").

Temporary objects

It is not necessary but it would be nice to be able to use temporary objects (decided by the form of the name, e. g. beginning with _) which exist only in an expression, deleted after the evaluation of the expression and do not even interfere with temporary objects in macro calls with the same name.

Listeners

Listeners would be an other new type of object which contain the description of an event (its type and possibly its parameters) and a macro which is executed when the event occurs. The parameters, depending on the type of the event, can further specify when it is triggered, analogously to the objName parameter of registerObjectUpdateListener in the JavaScript interface. It depends on the type of the event what kind of parameters (if any) the macro should have. They could be created by a command like Listener[Text type, List parameters, Macro handler] . In this case it is more important that they are objects because this way macros can simply store and if needed delete them, and they could be permanently stored in the files this way. The user could edit or delete them in the Properties window.

I propose the Add, Remove, Update and ObjectUpdate (parameter: the object) listeners as in the JavaScript interface and two additions:

• ObjectUpdate listeners could be defined for dependent objects too. In this case if the user attempts to drag the object (e. g. a point or a number of a slider), the macro is executed, and it sees the object like if it was at the place where the user dragged it (despite the fact that this is normally impossible) and it could modify its ancestors so that the dependent object indeed goes there. This way it would be easy to make dependent objects not only of the specific simple forms movable.
• Click (anywhere), ObjectClick (on a specific object, parameter: the object), AnyObjectClick (click on any object) and DrawingPadClick listeners for creating special listeners for convenience and buttons. ObjectClick is the most important. The parameters of the macro would be the place of the click as a value for Click and DrawingPadClick, and the object and the place of the click for ObjectClick and AnyObjectClick.

If an event triggers a listener, the objects depending on objects modified by the listener should be recalculated and the drawing pad should be repainted only after executing the listener.

Records could be used to store custom properties of objects and to group objects which belong together. I post it in an other topic because, although important, it is not completely necessary for scripting.

Class of the objects could be used to store the role of an object in the context of a kit of macros and to list every object of a role. I post it in an other topic because it is not completely necessary for scripting.

1

A solution, proposed by some people, would be to integrate a JavaScript interpreter into GeoGebra.

This has already been done, and will be demonstrated at the conference :)

Also GeoGebra 3.2 already has an (undocumented) plugin interface - get in touch by email if you're interested.

1

This has already been done, and will be demonstrated at the conference :)

That is great. I am looking forward to it and I hope that no serious drawbacks will evidence because of the fact that it is a language with a different structure.