44**Scripts **: Embedding script languages
55***************************************
66
7- In a lot of contexts, you want to give the possibility to users to extend
8- your application. This can be done in several ways: define an Ada API from
9- which they can build dynamically loadable modules, provide the whole source
10- code to your application and let users recompile it, interface with a simpler
11- scripting languages,...
12-
13- Dynamically loadable modules can be loaded on demand, as their name indicate.
14- However, they generally require a relatively complex environment to build,
15- and are somewhat less portable. But when your users are familiar with Ada,
16- they provide a programming environment in which they are comfortable.
17- As usual, changing the module requires recompilation, re-installation,...
18-
19- Providing the source code to your application is generally even more
20- complex for users. This requires an even more complex setup, your application
21- is generally too big for users to dive into, and modifications done by one
22- users are hard to provide to other users, or will be lost when you
23- distribute a new version of your application.
24-
25- The third solution is to embed one or more scripting languages in your
26- application, and export some functions to it. This often requires your users
27- to learn a new language, but these languages are generally relatively simple,
28- and since they are interpreted they are easier to learn in an interactive
29- console. The resulting scripts can easily be redistributed to other users or
30- even distributed with future versions of your application.
31-
32- The module in GNATColl helps you implement the third solution. It was
33- used extensively in the GPS programming environment for its python interface.
7+ Often, you may want users to extend your application. There are several ways to
8+ achieve this: you can define an Ada API for users to build dynamically loadable
9+ modules, provide your application's source code for users to modify and
10+ recompile, or interface with a simple scripting language.
11+
12+ Dynamically loadable modules can be loaded as needed, but they typically
13+ require a complex build environment and are less portable. They are ideal when
14+ your users are familiar with Ada, offering a comfortable programming
15+ environment. However, updating modules means recompiling and reinstalling.
16+
17+ Distributing your application's source code is even more complex for users. It
18+ demands a complicated setup, and your application may be too large for users to
19+ easily modify. Changes made by one user are difficult to share and may be lost
20+ when you release a new version.
21+
22+ A third approach is to embed one or more scripting languages in your application
23+ and expose certain functions to them. Users may need to learn a new language,
24+ but scripting languages are usually simple and interactive, making them easier
25+ to learn. Scripts can be easily shared among users or included in future
26+ releases of your application.
27+
28+ GNATColl helps you implement this third solution. It has been used extensively
29+ in the GNAT Studio programming environment for its Python interface.
3430
3531.. tip ::
3632
3733 Each of the scripting language is optional
3834
39- This module can be compiled with any of these languages as an optional
40- dependency (except for the shell language, which is always built-in, but is
41- extremely minimal, and doesn't have to be loaded at run time anyway).
42- If the necessary libraries are found on the system, GNATColl will
43- be build with support for the corresponding language, but your application
44- can chose at run time whether or not to activate the support for a specific
45- language.
35+ This module can be built with support for any of the available scripting
36+ languages as optional dependencies. Please note that the module itself does not
37+ include any scripting language by default.
4638
4739.. index :: test driver
4840.. index :: testing your application
4941
50- .. tip ::
42+ .. tip ::
5143
5244 Use a scripting language to provide an automatic testing framework for
5345 your application.
5446
55- The GPS environment uses python command for its *automatic test suite *,
56- including graphical tests such as pressing on a button, selecting a
57- menu,...
58-
5947.. _Supported_languages :
6048
6149Supported languages
6250===================
6351
64- The module provides built-in support for several scripting languages, and
65- other languages can "easily" be added. Your application does not change
66- when new languages are added, since the interface to export subprograms
67- and classes to the scripting languages is language-neutral, and will
68- automatically export to all known scripting languages.
69-
70- The Core component provides support for the following language:
71-
72- *Shell *
73- This is a very simple-minded scripting language, which doesn't provide
74- flow-control instructions (:ref: `The_Shell_language `).
75-
76- Optional components add support for other languages, e.g. Python. Please
77- refer to the corresponding component's documentation.
78-
79-
80- .. _The_Shell_language :
81-
82- The Shell language
83- ------------------
84-
85- The shell language was initially developed in the context of the GPS
86- programming environment, as a way to embed scripting commands in XML
87- configuration files.
88-
89- In this language, you can execute any of the commands exported by the
90- application, passing any number of arguments they need. Arguments to function
91- calls can, but need not, be quoted. Quoting is only mandatory when they
92- contain spaces, newline characters, or double-quotes ('"'). To quote an
93- argument, surround it by double-quotes, and precede each double-quote it
94- contains by a backslash character. Another way of quoting is similar to
95- what python provides, which is to triple-quote the argument, i.e. surround it
96- by '"""' on each side. In such a case, any special character (in particular
97- other double-quotes or backslashes) lose their special meaning and are just
98- taken as part of the argument. This is in particular useful when you do not
99- know in advance the contents of the argument you are quoting::
100-
101- Shell> function_name arg1 "arg 2" """arg 3"""
102-
103- Commands are executed as if on a stack machine: the result of a command is
104- pushed on the stack, and later commands can reference it using `% `
105- following by a number. By default, the number of previous results that are
106- kept is set to 9, and this can only be changed by modifying the source code
107- for GNATColl. The return values are also modified by commands executed
108- internally by your application, and that might have no visible output from
109- the user's point of view. As a result, you should never assume you know
110- what `%1 `,... contain unless you just executed a command in the
111- same script::
112-
113- Shell> function_name arg1
114- Shell> function2_name %1
115-
116- In particular, the `%1 ` syntax is used when emulating object-oriented
117- programming in the shell. A method of a class is just a particular function
118- that contains a '.' in its name, and whose first implicit argument is the
119- instance on which it applies. This instance is generally the result of
120- calling a constructor in an earlier call. Assuming, for instance, that we
121- have exported a class "Base" to the shell from our Ada core, we could use
122- the following code::
123-
124- Shell> Base arg1 arg2
125- Shell> Base.method %1 arg1 arg2
126-
127- to create an instance and call one of its methods.
128- Of course, the shell is not the best language for object-oriented programming,
129- and better languages should be used instead.
130-
131- When an instance has associated properties (which you can export from Ada
132- using `Set_Property `), you access the properties by prefixing its name
133- with "@"::
134-
135- Shell> Base arg1 arg2 # Build new instance
136- Shell> @id %1 # Access its "id" field
137- Shell> @id %1 5 # Set its "id" field
138-
139-
140- Some commands are automatically added to the shell when this scripting
141- language is added to the application. These are
142-
143- .. index :: Function load
144-
145- `Function load (file) `
146- Loads the content of `file ` from the disk, and execute each of its lines as
147- a Shell command. This can for instance be used to load scripts when your
148- application is loaded
149-
150- .. index :: Function echo
151-
152- `Function echo (arg...) `
153- This function takes any number of argument, and prints them in the console
154- associated with the language. By default, when in an interactive console, the
155- output of commands is automatically printed to the console. But when you
156- execute a script through `load ` above, you need to explicitly call
157- `echo ` to make some output visible.
158-
159- .. index :: Function clear_cache
160-
161- `Function clear_cache `
162- This frees the memory used to store the output of previous commands. Calling
163- `%1 ` afterward will not make sense until further commands are executed.
52+ Your application does not need to be modified when new scripting languages are
53+ added, because the interface for exporting subprograms and classes is
54+ language-neutral and automatically makes them available to all supported
55+ scripting languages.
16456
57+ Support for Python scripting is available through the GNATCOLL bindings
58+ component. For more information, please consult that component's documentation.
59+ Since GNATCOLL Core does not include any scripting language itself, the
60+ documentation examples primarily use the Python scripting support.
16561
16662.. _Classes_exported_to_all_languages :
16763
16864Classes exported to all languages
16965---------------------------------
17066
17167In addition to the functions exported by each specific scripting language,
172- as described above, GNATColl exports the following to all the
68+ GNATColl exports the following to all the
17369scripting languages. These are exported when your Ada code calls the
17470Ada procedure `GNATCOLL.Scripts.Register_Standard_Classes `, which should
17571done after you have loaded all the scripting languages.
@@ -370,16 +266,8 @@ This is done through a simple call to one or more subprograms. The following
370266example registers both the shell and python languages::
371267
372268 with GNATCOLL.Scripts.Python;
373- with GNATCOLL.Scripts.Shell;
374- Register_Shell_Scripting (Repo);
375269 Register_Python_Scripting (Repo, "MyModule");
376270
377- .. index :: Procedure Register_Shell_Scripting
378-
379- `Procedure Register_Shell_Scripting (Repo) `
380- This adds support for the shell language. Any class or function that is
381- now exported through GNATColl will be made available in the shell
382-
383271.. index :: Procedure Register_Python_Scripting
384272
385273`Procedure Register_Python_Scripting (Repo, Module_Name) `
@@ -473,7 +361,7 @@ need to be overriden.
473361 language, so that when the user presses :kbd: `enter ` they know which language
474362 must execute the command
475363
476- .. index :: Virtual_Console.Read
364+ .. index :: Virtual_Console.Read
477365
478366`Virtual_Console.Read (Size, Whole_Line) : String `
479367 Read either several characters or whole lines from the console. This is
@@ -526,7 +414,7 @@ To make it possible for users to create their own consoles, you need to
526414export a `Constructor_Method ` (see below) for the `Console `
527415class. In addition to your own processing, this constructor needs also to
528416call::
529-
417+
530418 declare
531419 Inst : constant Class_Instance := Nth_Arg (Data, 1);
532420 begin
@@ -629,7 +517,7 @@ of the role of each type:
629517 myconsole = Console ("title") # Create new console
630518 myconsole.mydata = "20060619" # Any data, really
631519 myconsole = Console ("title2") # Create another window
632- myconsole = Console ("title") # Must be same as first,
520+ myconsole = Console ("title") # Must be same as first,
633521 print myconsole.mydata # so that this prints "20060619"
634522
635523.. index :: Class Instance_Property
@@ -672,10 +560,7 @@ of the role of each type:
672560
673561Although the exact way they are all these types are created is largely
674562irrelevant to your specific application in general, it might be useful for you
675- to override part of the types to provide more advanced features. For instance,
676- GPS redefines its own Shell language, that has basically the same behavior as
677- the Shell language described above but whose `Subprogram_Record ` in fact
678- execute internal GPS actions rather than any shell code.
563+ to override part of the types to provide more advanced features
679564
680565.. _Exporting_functions :
681566
@@ -974,8 +859,8 @@ There are two ways to work around that limitation:
974859 ed2 = Editor.get ("file.adb")
975860 => Return existing instance
976861 ed == ed2
977- => True
978-
862+ => True
863+
979864 .. highlight :: ada
980865
981866 The corresponding Ada code would be something like::
@@ -1024,7 +909,7 @@ There are two ways to work around that limitation:
1024909 => ed is of type MyClassImpl
1025910 ed = MyClass ("file.adb") # return same instance
1026911 ed.do_something()
1027-
912+
1028913
1029914 It is important to realize that in the call above, we are not calling
1030915 the constructor of a class, but a function. At the Ada level, the function
@@ -1039,7 +924,7 @@ There are two ways to work around that limitation:
1039924 MyClass "file.adb"
1040925 => <MyClassImpl_Instance_0x12345>
1041926 MyClassImpl.do_something %1
1042-
927+
1043928 and the new name of the class is visible in the method call.
1044929
1045930
0 commit comments