Gambas 脚本
介绍
Gambas Scripter是Gambas解释器的一个基于文本的前端。应用程序/脚本是可由任何Linux编辑器编辑的简单文本文件。这些脚本是需要程序员处理编写脚本而BASH不能提供复杂数据类型和数据处理的绝佳办法。操作系统识别Gambas脚本的mime类型的方式与识别BASH或DASH脚本的方式相同。
Scripter很好地集成到Linux shell环境中,通过 env[<env variable>] 可以直接访问shell环境变量。
Scripter不需要完整的Gambas IDE提供的复杂接口。事实上,使用Gambas脚本根本不需要IDE。
Scripter是BASH的一个很好的替代方案,可以快速实现复杂的系统管理过程,为程序员带来一种实现良好的全方位的编程语言。这允许脚本使用图形和文本基础界面。
Gambas脚本在编译时会进行优化,并且只有在脚本发生更改时才会缓存和重新编译编译编译后的脚本。这大大提高了运行Gambas脚本时的系统性能和响应能力。
Scripter还可以用于编译和执行更传统的Gambas项目。
自从 3.16
Scripter may also be used as a component to a Gambas Application allowing the application to dynamically load or
create text based scripts which can be directly loaded and executed by the application. The loaded script will have access
to the applications classes and public class variables.
Note:
Throughout this document Scripter and gbs3 are used interchangeably.
The actual linux executable is gbs3
Scripter - How it works
The Scripter(gbs3) works by:
creating a temporary project from your script,
compiling it,
and running it.
自从 3.16
The Gambas Scripter gbs3 can also directly execute a project without the use of the IDE.
The compiled project is cached so that it is executed immediately if you run the project again.
The Scripter can also be used to generate a component which can be loaded and used at runtime.
Example: directly execute a script file
> gbs3 ~/myscripts/script1.gbs
> ./script1.gbs
自从 3.16
Example: directly execute a project
> gbs3 ~/myprojects/project1
Creating a Script
To create a Gambas script file, make it executable and write this preamble at the beginning:
The Scripter can execute free-form programs with ease.
To achieve this, Scripter will collect your free-form commands into a Main() subroutine automatically
while maintaining the integrity of subroutines/structures/class separately.
sub PrintBye()
print "Bye"
end
dim sHello as string = "Hello"
Print sHello
PrintBye()
The Gambas script can also be written like a module in a common Gambas project,
the interpreter automatically executes a Main() subroutine when included in the script.
TIP: Scripts execute more quickly if your code includes a Sub Main() subroutine rather
than using the free-form method of writing a script.
This is due to the Scripter not having to collect the free-form code and create a Main() subroutine.
#!/usr/bin/env gbs3
Public Sub Main()
DoPrintHello()
End
Private Sub DoPrintHello()
Print "Hello"
End
The code can be organized with private and public subs and functions, and
constants and variables just like in Gambas modules inside Gambas projects.
Installing Scripter - gbs3
Scripter is not installed by default when the IDE is installed onto your system. It must explicitly be installed before it is available.
It needs to be installed through your distributions package manager.
For example on Mint/Ubuntu the following command could be used
sudo apt install gambas3-gb-scripter
See your distribution package manager for specifics.
To use Scripter it is not required to have the Gambas3 IDE installed.
Scripter can be installed standalone. When installed Scripter will cause the gambas-devel package
containing the compiler linker and archiver to be installed and also the gb.pcre component
if they are not already present on the system.
When installed standalone, the user will be required to individually install any components needed by executed scripts.
Defining Classes and Structures within a Gambas script
Unlike a Gambas project, Scripts support Classes and Structures in a script-specific way.
Classes are defined inline within your script code, structures must be public and defined before any reference to them in the script.
Defining a class inline
To define a class the following format is used:
Public oMyClass as new MyClass
class MyClass
sub sub1()
print "hello"
end
end class
A Class's data and functions are defined in the same way as in the IDE except you must add the Class and End Class statement.
Notice that the class does not have to be defined before it is used.
Defining a structure inline
Structures, which are a special case of class, must be defined before any reference to that structure.
All structures must be declared as Public and are Global.
Examples of defining Structures
#!/usr/bin/env gbs3
Public sMyVar1 as string
Public oMystruct as new MyStruct
Public Struct MyStruct
sText as string
end struct
oMystruct.sText = "hello"
The above example will fail!
The correct method is
#!/usr/bin/env gbs3
Public sMyVar1 as string
public struct MyStruct
sText as string
end struct
Public oMystruct as new MyStruct
oMystruct.sText = "hello"
Executing a Gambas script
There are two ways to execute a Gambas script
You may create a non-executable file as in the example below.
From a file named MyScript.gbs containing:
Public Sub Main()
DoPrintHello()
End
Private Sub DoPrintHello()
Print "Hello"
End
This may be executed with:
An alternative to this, and most commonly used, is to provide the command inside the file and make it executable.
From the file myscript.gbs containing the following:
#!/usr/bin/env gbs3
Public Sub Main()
DoPrintHello()
End
Private Sub DoPrintHello()
Print "Hello"
End
If the file is made executable with
Then it can be executed with the simple command:
from the current directory. If we want to make this a command for general personal use
it can be copied to:
or for more general use to:
Passing Arguments To The Script
There is an ARGS[] array which contains arguments passed by command line.
#!/usr/bin/env gbs3
Dim arg as String
Dim i as Integer
for each arg in ARGS
Print "Argument Nr. " & i & " = " & arg
Inc i
next
See that position 0 of ARGS is used by Gambas itself, it contains the path to the cached compiled project:
$ ./test.gbs ding dong
Argument Nr. 0 = /tmp/gambas.1000/script-cache/b1826db433d3855de7e021ca9ad34b87/test.gbs
New for 3.15.3 Arg 0 now reports the name of the script correctly as test.gbs
Argument Nr. 1 = ding
Argument Nr. 2 = dong
Note: It is possible to get the name of your original script using file.name(args[0])
Using Scripter gbs3 as a component in your project
自从 3.16
It is possible to use Scripter gbs3 as a component in your project.
Scripter provides three interfaces:
The first is for dynamically loading plugins and is defined as follows:
'' This allows integration of scripter into an application that uses plugins
'' the call would be ScripterPlugin(MyScript,"-b -c etc these are other parameters")
'' This returns the instantiated class of the plugin script
ScripterPlugin(ScriptPath As String, Optional CompileParameters As String[] = [],
PluginNewParameters As Variant[] = Null) As Variant
ScripterPlugin.fromString(ScriptName As String,ScriptText as string,
Optional CompileParameters As String[] = [],
PluginNewParameters As Variant[] = Null) As Variant
ScripterPlugin.SetVerbose() 'Turns on verbose information
The second allows the execution of a script from text and return its output
ScripterExecute(ScriptName as string,ScriptText As String,
Optional CompileParameters As String[] = [],
PluginNewParameters As Variant[]) as variant
and the third is for executing a script directly returning the exit code and is defined as follows:
'' execute a script and return the exit code
'' aArgs[0] being the script name
Scriptmain.ScripterMain(aArgs As String[]) As Integer
Loading the gbs3 component
自从 3.16
To include gbs3 as a component in your application the following code is required
dim Scripter,ScriptMain,ScriptExecute as object
component.load(system.find("gbs3"))
Scripter = class.load("ScripterPlugin").new()
ScriptExecute = class.load("ScripterExecute").new()
Scriptmain = class.load("ScriptMain").new()
once this is done it is just a matter of calling the interface
dim myplugin1 as object = Scripter("~/myplugins/MyPlugin1")
myPlugin1()
dim myplugin2 as object = Scripter.fromString("MyClass","print \"Hello World\"")
myPlugin2()
or to execute a text script and get the output
dim result as variant
result = ScriptExecute("MyClass2","Print \"hello world\"\nPrint \"This is also returned\"")
or to execute a script by passing the command line parameters returning the exit code for example:
dim result as integer
result = ScriptMain.ScripterMain(["-v","-f","~/myscripts/MyScript1.gbs","Script parm1","Parm2"])
Creating Plugins using Scripter --plugin
自从 3.16
Scripter can create plugins that can be used by other scripts or Gambas applications after being built using the
--plugin or -p option. The term plugin is synonymous with the term component throughout this document.
Plugins are created in a user-selected directory and are also executed from and cached in this
directory, unlike a normal script, in which executables are created in the temp directory and are executed from
there. This allows plugins to persist after the Scripter exits.
When a plugin script is cached it will not be recompiled Scripter will return with no error.
If no output destination is specified, then the plugin is created in the:
~/.local/lib/gambas directory.
Plugins may be loaded from there using the component.load() function.
Scripts being used as plugins are generated with the entry point defined as
with a class of the same name as the basename of the script
_Call(...) as variant
by default.
A Scripter generated plugin source may look like this for a plugin script
from:
to:
Class MyPlugin1
public sub _Call(...) as variant
print "hello"
end
end class
So inside your script the parameters are accessed using the param gambas class.
It is also possible to define the entry point yourself with fixed parameters.
_Call(counter as integer) as integer
from:
public sub _Call(count as integer) as integer
print count
end
to:
class MyPlugin1
public sub _Call(count as integer) as integer
print count
end
end class
Example: Building an App that uses plugins
自从 3.16
Define some simple plugins/components for testing
~/myscripts/MyPlugin1.gbs:
print "The Parameter was",param[0]
return "This was done"
~/myscripts/MyPlugin2.gbs:
print "Number of parameters passed=",param.count
return "So was this"
~/myscripts/MyPlugin3.gbs:
public sub _Call(counter as integer) as integer
for i as integer = 0 to counter
print i;
next
return i
end
Execute gbs3 to create a component plugin.
> gbs3 --plugin ~/myscripts/MyPlugin1.gbs ~/myplugins
> gbs3 --plugin ~/myscripts/MyPlugin2.gbs ~/myplugins
> gbs3 --plugin ~/myscripts/MyPlugin3.gbs ~/myplugins
Now in the script that requires the plugin, they can be loaded as in the following script:
#!/usr/bin/env gbs3
dim MyPlugin1,MyPlugin2,MyPlugin3 as object
' Make sure we have the latest version, assume all compiles are perfect..
exec ["gbs3","--plugin","~/myscripts/MyPlugin1.gbs","~/myplugins"] 'if already in cache and no change then just returns
exec ["gbs3","--plugin","~/myscripts/MyPlugin2.gbs","~/myplugins"]
exec ["gbs3","--plugin","~/myscripts/MyPlugin3.gbs","~/myplugins"]
' Load the plugins
component.load(User.home &/ "/myplugins/MyPlugin1")
MyPlugin1 = class.load("MyPlugin1").new()
component.load(User.home &/ "/myplugins/MyPlugin2")
MyPlugin2 = class.load("MyPlugin2").new()
component.load(User.home &/ "/myplugins/MyPlugin3")
MyPlugin3 = class.load("MyPlugin3").new()
' Now lets access and call the plugin
print MyPlugin1("some parameter")
print MyPlugin2("one","two","three")
print MyPlugin3(100)
This ability is most useful in an application which creates the script on the fly and then incorporates it
into the application with access to all application classes.
#!/usr/bin/env gbs3
dim thenewone as object
file.sav