[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Documentation of gb.args and gb.highlight - Gambas
[Thread Prev] | [Thread Next]
- Subject: Documentation of gb.args and gb.highlight - Gambas
- From: Olivier Cruilles <olivier.cruilles@xxxxxxxx>
- Date: Wed, 29 Apr 2026 16:45:48 -0400
- To: user@xxxxxxxxxxxxxxxxxxxxxx
Hello everyone,I would like to share with you 2 little documentations regarding gb.args and gb.highlight component in Gambas.
As the original documentations for both components were not enough to clearly use them (on my opinion), I decided to created two new little docs with more details.
I have attached both of them docs in format Markdown Gambas (like that they could be added in the wiki of Gambas easily), and also both docs in HTML to show you what they are.
Let me know if you find glitches or errors in those docs please.Now the question is where to place them into the Gambas Wiki, which section will be the best please ?
-- Olivier
Usage guide for the gb.highlight component with TextEditor
-
The
gb.highlightcomponent is the modern syntax highlighting engine for Gambas (which replaces the oldgb.eval.highlight). It works together with thegb.form.editorcomponent (which provides theTextEditorwidget). -
Although very powerful, its internal operation with the
TextEditorhas a few architectural subtleties that are crucial to understand to prevent custom themes from not being displayed.
1. Basic concepts
To highlight text, the engine needs two things:-
A syntax file (
.highlight): It contains the regular expressions and rules that split the text and assign it logical "States" or "Styles" (e.g. Keyword, String, Comment). -
A theme file (
.theme): It maps these logical "States" to actual colors and font styles (Bold, Italic, etc.).
Create a syntax file (mylanguage.highlight)
Rules are read from top to bottom (the first that matches is applied).
#Basic example
comment {Comment}:
From "//"
string.double {String}:
From "\"" To "\""
keyword {Keyword}:
keyword If Else Then For While return
comment {Comment}:
From "//"
string.double {String}:
From "\"" To "\""
keyword {Keyword}:
keyword If Else Then For While return
Create a theme file (mylanguage.theme)
Configuration file mapping logical styles to colors.
[Gambas Highlighting Theme 1.0]
Background = "#FFFFFF"
Normal = "#000000"
Comment = "#008000,Oblique"
String = "#A31515"
Keyword = "#0000FF,Bold"
Background = "#FFFFFF"
Normal = "#000000"
Comment = "#008000,Oblique"
String = "#A31515"
Keyword = "#0000FF,Bold"
2. The Theme loading "Trap" (MUST READ)
The most common mistake when assigning a custom theme is using the method this way:TextEditor1.Theme.Load("./mylanguage.theme") ❌ (DOES NOT WORK AS EXPECTED)
Why
Gambas's architecture defines TextHighlighterTheme.Load(...) as a static method that generates and returns a brand new object TextHighlighterTheme. If the return is not explicitly captured to overwrite the editor's theme, the file is read into the void and the editor does not change color.
The right way:
You must replace the editor's Theme object with the new generated object:
TextEditor1.Theme = TextHighlighterTheme.Load("./mylanguage.theme") ✅
3. The initialization "Trap" (Form_Open)
When theForm_Open event is triggered, the TextEditor widget is not yet fully drawn on the screen. If you apply syntax highlighting at this precise moment, the internal C++ cache might ignore the colors.
The right way:
The recommended trick by the Gambas IDE is to defer the loading of the editor's configuration by a few milliseconds using a Timer object.
4. Complete and Robust Example Code
Here is the standard and robust code to implement your custom syntax highlighting in your form:' Declaration of the Timer to defer the display
Private $TimerOpening As Timer
Public Sub Form_Open()
' 1. Registration of the syntax in the global engine
' (Internal_name, Display_name, File_path)
If Not TextHighlighter.List.Exist("mylanguage") Then
TextHighlighter.Register("mylanguage", "My Language", "./mylanguage.highlight")
End If
' 2. Launch the Timer to configure the editor after opening the window
$TimerOpening = New Timer As "TimerOpening"
$TimerOpening.Delay = 10 ' 10 milliseconds are enough
$TimerOpening.Start()
End
Public Sub TimerOpening_Timer()
$TimerOpening.Stop()
' Make sure our language has been registered properly
If TextHighlighter.List.Exist("mylanguage") Then
' A. Tell the editor which syntax to use
TextEditor1.Highlight = "mylanguage"
' B. Replace the WHOLE Theme object of the editor with the new loaded Theme
If Exist("./mylanguage.theme") Then
TextEditor1.Theme = TextHighlighterTheme.Load("./mylanguage.theme")
Endif
' C. Force redrawing of the editor with these new rules
TextEditor1.Refresh()
End If
' Optional: Load your text and give focus
' TextEditor1.Text = File.Load("my_code.txt")
TextEditor1.Goto(0, 0, True)
TextEditor1.SetFocus()
End
Private $TimerOpening As Timer
Public Sub Form_Open()
' 1. Registration of the syntax in the global engine
' (Internal_name, Display_name, File_path)
If Not TextHighlighter.List.Exist("mylanguage") Then
TextHighlighter.Register("mylanguage", "My Language", "./mylanguage.highlight")
End If
' 2. Launch the Timer to configure the editor after opening the window
$TimerOpening = New Timer As "TimerOpening"
$TimerOpening.Delay = 10 ' 10 milliseconds are enough
$TimerOpening.Start()
End
Public Sub TimerOpening_Timer()
$TimerOpening.Stop()
' Make sure our language has been registered properly
If TextHighlighter.List.Exist("mylanguage") Then
' A. Tell the editor which syntax to use
TextEditor1.Highlight = "mylanguage"
' B. Replace the WHOLE Theme object of the editor with the new loaded Theme
If Exist("./mylanguage.theme") Then
TextEditor1.Theme = TextHighlighterTheme.Load("./mylanguage.theme")
Endif
' C. Force redrawing of the editor with these new rules
TextEditor1.Refresh()
End If
' Optional: Load your text and give focus
' TextEditor1.Text = File.Load("my_code.txt")
TextEditor1.Goto(0, 0, True)
TextEditor1.SetFocus()
End
Summary of key points
-
Always enable the
gb.highlightandgb.form.editorcomponents. -
Use
TextHighlighter.Registerto teach your syntax to the global engine. -
Assign the
TextEditor.Highlightbefore loading theTextEditor.Theme. -
Capture the return of
TextHighlighterTheme.Load(...)to inject it intoTextEditor.Theme. -
Use a short
Timerto apply everything once the view (GUI) is ready.
# Usage guide for the \
# [`gb.highlight` component with `TextEditor`]
@{index}
- The `gb.highlight` component is the modern syntax highlighting engine for Gambas (which replaces the old `gb.eval.highlight`). It works together with the `gb.form.editor` component (which provides the `TextEditor` widget).
- Although very powerful, its internal operation with the `TextEditor` has a few architectural subtleties that are crucial to understand to prevent custom themes from not being displayed.
## [1. Basic concepts]
To highlight text, the engine needs two things:
1. **A syntax file (`.highlight`)**: It contains the regular expressions and rules that split the text and assign it logical "States" or "Styles" (e.g. *Keyword*, *String*, *Comment*).
2. **A theme file (`.theme`)**: It maps these logical "States" to actual colors and font styles (Bold, Italic, etc.).
### [Create a syntax file (`mylanguage.highlight`)]
Rules are read from top to bottom (the first that matches is applied).
[[ code sh
#Basic example
comment {Comment}:
From "//"
string.double {String}:
From "\"" To "\""
keyword {Keyword}:
keyword If Else Then For While return
]]
### [Create a theme file (`mylanguage.theme`)]
Configuration file mapping logical styles to colors.
[[ code sh
[Gambas Highlighting Theme 1.0]
Background = "#FFFFFF"
Normal = "#000000"
Comment = "#008000,Oblique"
String = "#A31515"
Keyword = "#0000FF,Bold"
]]
## [2. The Theme loading "Trap" (MUST READ)]
The most common mistake when assigning a custom theme is using the method this way: \
`TextEditor1.Theme.Load("./mylanguage.theme")` ❌ **(DOES NOT WORK AS EXPECTED)**
**Why**
Gambas's architecture defines `TextHighlighterTheme.Load(...)` as a **static method** that generates and *returns a brand new object* `TextHighlighterTheme`. If the return is not explicitly captured to overwrite the editor's theme, the file is read into the void and the editor does not change color.
**The right way:**
You must replace the editor's Theme object with the new generated object:
`TextEditor1.Theme = TextHighlighterTheme.Load("./mylanguage.theme")` ✅
## [3. The initialization "Trap" (Form_Open)]
When the `Form_Open` event is triggered, the `TextEditor` widget is not yet fully drawn on the screen. If you apply syntax highlighting at this precise moment, the internal C++ cache might ignore the colors.
**The right way:**
The recommended trick by the Gambas IDE is to defer the loading of the editor's configuration by a few milliseconds using a `Timer` object.
## [4. Complete and Robust Example Code]
Here is the standard and robust code to implement your custom syntax highlighting in your form:
[[ code gambas
' Declaration of the Timer to defer the display
Private $TimerOpening As Timer
Public Sub Form_Open()
' 1. Registration of the syntax in the global engine
' (Internal_name, Display_name, File_path)
If Not TextHighlighter.List.Exist("mylanguage") Then
TextHighlighter.Register("mylanguage", "My Language", "./mylanguage.highlight")
End If
' 2. Launch the Timer to configure the editor after opening the window
$TimerOpening = New Timer As "TimerOpening"
$TimerOpening.Delay = 10 ' 10 milliseconds are enough
$TimerOpening.Start()
End
Public Sub TimerOpening_Timer()
$TimerOpening.Stop()
' Make sure our language has been registered properly
If TextHighlighter.List.Exist("mylanguage") Then
' A. Tell the editor which syntax to use
TextEditor1.Highlight = "mylanguage"
' B. Replace the WHOLE Theme object of the editor with the new loaded Theme
If Exist("./mylanguage.theme") Then
TextEditor1.Theme = TextHighlighterTheme.Load("./mylanguage.theme")
Endif
' C. Force redrawing of the editor with these new rules
TextEditor1.Refresh()
End If
' Optional: Load your text and give focus
' TextEditor1.Text = File.Load("my_code.txt")
TextEditor1.Goto(0, 0, True)
TextEditor1.SetFocus()
End
]]
### Summary of key points
* Always enable the `gb.highlight` and `gb.form.editor` components.
* Use `TextHighlighter.Register` to teach your syntax to the global engine.
* Assign the `TextEditor.Highlight` **before** loading the `TextEditor.Theme`.
* Capture the return of `TextHighlighterTheme.Load(...)` to inject it into `TextEditor.Theme`.
* Use a short `Timer` to apply everything once the view (GUI) is ready.
📚 The gb.args component — Complete guide
- 1. Context: two argument levels
-
2. The 5 methods of the
Argsclass (gb.args) - 3. Example 1: Minimal program with options
- 4. Example 2: With complete help text
- 5. Example 3: Options with default values and multiple types
- 6. Example 4: Option without value (flag) + option with mandatory value
- 7. Example 5: Error handling
- 8. Example 6: Complete professional CLI program
- 9. Important usage rules
- 10. Quick comparison
1. Context: two argument levels
In Gambas, there are two mechanisms to receive command line arguments:A. The Args class from the gb component (basic)
' Args is a static read-only array
Print Args.Count ' Total number of arguments (includes the program name)
Print Args.Max ' Index of the last argument (= Args.Count - 1)
Print Args.All.Join(" | ") ' All arguments separated by " | "
Print Args[0] ' Program name
Print Args[1] ' First passed argument
Example:
Print Args.Count ' Total number of arguments (includes the program name)
Print Args.Max ' Index of the last argument (= Args.Count - 1)
Print Args.All.Join(" | ") ' All arguments separated by " | "
Print Args[0] ' Program name
Print Args[1] ' First passed argument
$ gbx3 $HOME/MyApp -- hello world 42
Print Args.Count ' → 4
Print Args.Max ' → 3
Print Args.All.Join(" | ") ' → "MyApp | hello | world | 42"
Print Args[0] ' → "MyApp"
Print Args[1] ' → "hello"
Print Args[2] ' → "world"
Print Args[3] ' → "42"
Print Args.Max ' → 3
Print Args.All.Join(" | ") ' → "MyApp | hello | world | 42"
Print Args[0] ' → "MyApp"
Print Args[1] ' → "hello"
Print Args[2] ' → "world"
Print Args[3] ' → "42"
⚠️Argsfromgbis raw: everything is a string, no options parsing.
B. The Args class from the gb.args component (sophisticated)
The gb.args component (available since Gambas 3.4) provides a static Args class with 5 methods to properly parse options and arguments.
2. The 5 methods of the Args class (gb.args)
| Method | Role |
|---|---|
Begin([Usage As String])
| Starts parsing. Optional: help text |
End() As String[]
| Ends parsing, returns raw arguments |
Get(short, long, desc, argName) As String
| String option |
GetFloat(short, long[, desc, argName, default]) As Float
| Float option |
GetInteger(short, long[, desc, argName, default]) As Integer
| Integer option |
Has(short, long[, desc]) As Boolean
| Boolean option (flag) |
3. Example 1: Minimal program with options
' Main Module (Main)
Public Sub Main()
Args.Begin()
' String option : -f / --file
Dim sFichier As String
sFichier = Args.Get("f", "file", "Input file", "FILE")
' Boolean option (flag) : -v / --verbose
Dim bVerbose As Boolean
bVerbose = Args.Has("v", "verbose")
' Integer option with default value
Dim iTaille As Integer
iTaille = Args.GetInteger("s", "size", "Buffer size", "SIZE", 1024)
' Retrieve the remaining arguments (after --)
Dim aArgs As String[]
aArgs = Args.End()
' Display
Print "File: " & sFichier
Print "Verbose: " & bVerbose
Print "Size: " & iTaille
Print "Remaining arguments: " & aArgs.Join(", ")
End
Usage:
Public Sub Main()
Args.Begin()
' String option : -f / --file
Dim sFichier As String
sFichier = Args.Get("f", "file", "Input file", "FILE")
' Boolean option (flag) : -v / --verbose
Dim bVerbose As Boolean
bVerbose = Args.Has("v", "verbose")
' Integer option with default value
Dim iTaille As Integer
iTaille = Args.GetInteger("s", "size", "Buffer size", "SIZE", 1024)
' Retrieve the remaining arguments (after --)
Dim aArgs As String[]
aArgs = Args.End()
' Display
Print "File: " & sFichier
Print "Verbose: " & bVerbose
Print "Size: " & iTaille
Print "Remaining arguments: " & aArgs.Join(", ")
End
$ gbx3 $HOME/MyApp -- -f config.txt -s 2048 -- input1.txt input2.txt
File: config.txt
Verbose: False
Size: 2048
Remaining arguments: input1.txt, input2.txt
$ gbx3 $HOME/MyApp -- --verbose --file=data.ini -- arg1 arg2 arg3
File: data.ini
Verbose: True
Size: 1024
Remaining arguments: arg1, arg2, arg3
File: config.txt
Verbose: False
Size: 2048
Remaining arguments: input1.txt, input2.txt
$ gbx3 $HOME/MyApp -- --verbose --file=data.ini -- arg1 arg2 arg3
File: data.ini
Verbose: True
Size: 1024
Remaining arguments: arg1, arg2, arg3
4. Example 2: With complete help text
Public Sub Main()
Dim sMode As String
Dim fRatio As Float
Dim bForce As Boolean
Dim aArgs As String[]
Args.Begin(SetHelpText())
sMode = Args.Get("m", "mode", "Processing mode (fast|normal|deep)", "MODE")
fRatio = Args.GetFloat("r", "ratio", "Compression ratio", "RATIO", 0.75)
bForce = Args.Has("f", "force", "Force processing without confirmation")
aArgs = Args.End()
Print "Mode: " & sMode
Print "Ratio: " & fRatio
Print "Force: " & bForce
Print "Args: " & aArgs.Join(", ")
End
Private Function SetHelpText() As String
Dim sText As String
sText &= gb.NewLine
sText &= "MyApp - Image processing" & gb.NewLine
sText &= gb.NewLine
sText &= "Usage: gbx3 /path/to/project -- [options] [-- <args>]" & gb.NewLine
sText &= gb.NewLine
sText &= "Example: gbx3 $HOME/MyApp -- -m deep -r 0.5 -- img1.png img2.png" & gb.NewLine
sText &= gb.NewLine
sText &= "Options:" & gb.NewLine
sText &= " -m --mode <MODE> Processing mode (fast|normal|deep)" & gb.NewLine
sText &= " -r --ratio <RATIO> Compression ratio (default: 0.75)" & gb.NewLine
sText &= " -f --force Force processing" & gb.NewLine
sText &= " -V --version Display the version" & gb.NewLine
sText &= " -h --help Display this help" & gb.NewLine
Return sText
End
Dim sMode As String
Dim fRatio As Float
Dim bForce As Boolean
Dim aArgs As String[]
Args.Begin(SetHelpText())
sMode = Args.Get("m", "mode", "Processing mode (fast|normal|deep)", "MODE")
fRatio = Args.GetFloat("r", "ratio", "Compression ratio", "RATIO", 0.75)
bForce = Args.Has("f", "force", "Force processing without confirmation")
aArgs = Args.End()
Print "Mode: " & sMode
Print "Ratio: " & fRatio
Print "Force: " & bForce
Print "Args: " & aArgs.Join(", ")
End
Private Function SetHelpText() As String
Dim sText As String
sText &= gb.NewLine
sText &= "MyApp - Image processing" & gb.NewLine
sText &= gb.NewLine
sText &= "Usage: gbx3 /path/to/project -- [options] [-- <args>]" & gb.NewLine
sText &= gb.NewLine
sText &= "Example: gbx3 $HOME/MyApp -- -m deep -r 0.5 -- img1.png img2.png" & gb.NewLine
sText &= gb.NewLine
sText &= "Options:" & gb.NewLine
sText &= " -m --mode <MODE> Processing mode (fast|normal|deep)" & gb.NewLine
sText &= " -r --ratio <RATIO> Compression ratio (default: 0.75)" & gb.NewLine
sText &= " -f --force Force processing" & gb.NewLine
sText &= " -V --version Display the version" & gb.NewLine
sText &= " -h --help Display this help" & gb.NewLine
Return sText
End
--help output:
MyApp - Image processing
Usage: gbx3 /path/to/project -- [options] [-- <args>]
Example: gbx3 $HOME/MyApp -- -m deep -r 0.5 -- img1.png img2.png
Options:
-m --mode <MODE> Processing mode (fast|normal|deep)
-r --ratio <RATIO> Compression ratio (default: 0.75)
-f --force Force processing
-V --version Display the version
-h --help Display this help
Usage: gbx3 /path/to/project -- [options] [-- <args>]
Example: gbx3 $HOME/MyApp -- -m deep -r 0.5 -- img1.png img2.png
Options:
-m --mode <MODE> Processing mode (fast|normal|deep)
-r --ratio <RATIO> Compression ratio (default: 0.75)
-f --force Force processing
-V --version Display the version
-h --help Display this help
5. Example 3: Options with default values and multiple types
Public Sub Main()
Dim sHost As String
Dim iPort As Integer
Dim fTimeout As Float
Dim bDebug As Boolean
Dim bQuiet As Boolean
Dim aUrls As String[]
Args.Begin("MyApp - HTTP Client")
' String with default
sHost = Args.Get("h", "host", "Target server", "HOST", "localhost")
' Integer with default
iPort = Args.GetInteger("p", "port", "Server port", "PORT", 8080)
' Float with default
fTimeout = Args.GetFloat("t", "timeout", "Timeout in seconds", "TIMEOUT", 30.0)
' Boolean flags
bDebug = Args.Has("d", "debug")
bQuiet = Args.Has("q", "quiet")
' Remaining arguments (URLs)
aUrls = Args.End()
If Not bQuiet Then
Print "Connecting to " & sHost & ":" & iPort
Print "Timeout: " & fTimeout & "s"
Print "Debug: " & bDebug
Print "URLs: " & aUrls.Join(", ")
Endif
End
Usages:
Dim sHost As String
Dim iPort As Integer
Dim fTimeout As Float
Dim bDebug As Boolean
Dim bQuiet As Boolean
Dim aUrls As String[]
Args.Begin("MyApp - HTTP Client")
' String with default
sHost = Args.Get("h", "host", "Target server", "HOST", "localhost")
' Integer with default
iPort = Args.GetInteger("p", "port", "Server port", "PORT", 8080)
' Float with default
fTimeout = Args.GetFloat("t", "timeout", "Timeout in seconds", "TIMEOUT", 30.0)
' Boolean flags
bDebug = Args.Has("d", "debug")
bQuiet = Args.Has("q", "quiet")
' Remaining arguments (URLs)
aUrls = Args.End()
If Not bQuiet Then
Print "Connecting to " & sHost & ":" & iPort
Print "Timeout: " & fTimeout & "s"
Print "Debug: " & bDebug
Print "URLs: " & aUrls.Join(", ")
Endif
End
# With all default options
$ gbx3 $HOME/MyApp -- --host api.example.com --port 443 -- https://api.example.com/data
Connecting to api.example.com:443
Timeout: 30.0s
Debug: False
URLs: https://api.example.com/data
# With flags and custom values
$ gbx3 $HOME/MyApp -- -d -t 60.5 -- https://api1.com https://api2.com
Connecting to localhost:8080
Timeout: 60.5s
Debug: True
URLs: https://api1.com, https://api2.com
$ gbx3 $HOME/MyApp -- --host api.example.com --port 443 -- https://api.example.com/data
Connecting to api.example.com:443
Timeout: 30.0s
Debug: False
URLs: https://api.example.com/data
# With flags and custom values
$ gbx3 $HOME/MyApp -- -d -t 60.5 -- https://api1.com https://api2.com
Connecting to localhost:8080
Timeout: 60.5s
Debug: True
URLs: https://api1.com, https://api2.com
6. Example 4: Option without value (flag) + option with mandatory value
Public Sub Main()
Dim sOutput As String
Dim bList As Boolean
Dim bVersion As Boolean
Dim aFiles As String[]
Args.Begin("MyApp - File manager")
' Option with mandatory value (no default)
sOutput = Args.Get("o", "output", "Output file", "FILE")
' Flag (boolean)
bList = Args.Has("l", "list", "List files")
' Note: -V and -h are handled automatically by gb.args
aFiles = Args.End()
If bList Then
Print "File list:"
Print aFiles.Join(gb.NewLine)
Else
Print "Output to: " & sOutput
Endif
End
Usage:
Dim sOutput As String
Dim bList As Boolean
Dim bVersion As Boolean
Dim aFiles As String[]
Args.Begin("MyApp - File manager")
' Option with mandatory value (no default)
sOutput = Args.Get("o", "output", "Output file", "FILE")
' Flag (boolean)
bList = Args.Has("l", "list", "List files")
' Note: -V and -h are handled automatically by gb.args
aFiles = Args.End()
If bList Then
Print "File list:"
Print aFiles.Join(gb.NewLine)
Else
Print "Output to: " & sOutput
Endif
End
# Mandatory -o option
$ gbx3 $HOME/MyApp -- -o result.txt file1.txt file2.txt
Output to: result.txt
# -l flag
$ gbx3 $HOME/MyApp -- -l -- file1.txt file2.txt
File list:
file1.txt
file2.txt
# Version (handled automatically)
$ gbx3 $HOME/MyApp -- --version
0.1.0
# Help (handled automatically)
$ gbx3 $HOME/MyApp -- -h
MyApp - File manager
Usage: gbx3 /path/to/project -- [options] [-- <args>]
Options:
-o --output <FILE> Output file
-l --list List files
-V --version Display the version
-h --help Display this help
$ gbx3 $HOME/MyApp -- -o result.txt file1.txt file2.txt
Output to: result.txt
# -l flag
$ gbx3 $HOME/MyApp -- -l -- file1.txt file2.txt
File list:
file1.txt
file2.txt
# Version (handled automatically)
$ gbx3 $HOME/MyApp -- --version
0.1.0
# Help (handled automatically)
$ gbx3 $HOME/MyApp -- -h
MyApp - File manager
Usage: gbx3 /path/to/project -- [options] [-- <args>]
Options:
-o --output <FILE> Output file
-l --list List files
-V --version Display the version
-h --help Display this help
7. Example 5: Error handling
Public Sub Main()
Try
Args.Begin(SetHelpText())
Dim sMode As String
sMode = Args.Get("m", "mode", "Mode (fast|normal|deep)", "MODE")
' Default value if option not specified
If sMode = "" Then
sMode = "normal"
Endif
Args.End()
Print "Selected mode: " & sMode
Catch
' gb.args exits with code 1 in case of a parsing error
' (unknown option, missing value, etc.)
Print "Command line error: " & Error.Text
Quit 1
End
End
Common errors:
Try
Args.Begin(SetHelpText())
Dim sMode As String
sMode = Args.Get("m", "mode", "Mode (fast|normal|deep)", "MODE")
' Default value if option not specified
If sMode = "" Then
sMode = "normal"
Endif
Args.End()
Print "Selected mode: " & sMode
Catch
' gb.args exits with code 1 in case of a parsing error
' (unknown option, missing value, etc.)
Print "Command line error: " & Error.Text
Quit 1
End
End
# Unknown option → exits with code 1
$ gbx3 $HOME/MyApp -- -z badoption
gb.args: unknown option 'z'
# Option with missing value → exits with code 1
$ gbx3 $HOME/MyApp -- -m
gb.args: option 'm' requires an argument
# -o option without value → default value = ""
$ gbx3 $HOME/MyApp -- --output
Output to: (empty)
$ gbx3 $HOME/MyApp -- -z badoption
gb.args: unknown option 'z'
# Option with missing value → exits with code 1
$ gbx3 $HOME/MyApp -- -m
gb.args: option 'm' requires an argument
# -o option without value → default value = ""
$ gbx3 $HOME/MyApp -- --output
Output to: (empty)
8. Example 6: Complete professional CLI program
' Main Module
Public Sub Main()
Dim sAction As String
Dim sConfig As String
Dim iVerbosity As Integer
Dim bDryRun As Boolean
Dim bVersion As Boolean
Dim aTargets As String[]
Args.Begin(BuildHelp())
sAction = Args.Get("a", "action", "Action (init|deploy|rollback|status)", "ACTION")
sConfig = Args.Get("c", "config", "Configuration file", "CONFIG", "/etc/myapp/config.ini")
iVerbosity = Args.GetInteger("v", "verbose", "Verbosity level (0-3)", "LEVEL", 0)
bDryRun = Args.Has("n", "dry-run", "Dry run")
bVersion = Args.Has("", "version")
aTargets = Args.End()
Select Case sAction
Case "init"
Print "[INIT] Configuration: " & sConfig
Case "deploy"
Print "[DEPLOY] Target: " & aTargets.Join(", ")
If bDryRun Then Print " (DRY-RUN - no real changes)"
Case "rollback"
Print "[ROLLBACK] Previous version restored"
Case "status"
Print "[STATUS] In progress..."
Case ""
Print "Error: --action is mandatory"
Print "Use -h for help"
Quit 1
Case Else
Print "Error: unknown action '" & sAction & "'"
Quit 1
End Select
Print "Verbosity: " & iVerbosity
End
Private Function BuildHelp() As String
Dim h As String
h &= gb.NewLine
h &= "MyApp v1.2.3 - Deployment manager" & gb.NewLine
h &= gb.NewLine
h &= "Usage: gbx3 /project -- [options] [-- <targets>]" & gb.NewLine
h &= gb.NewLine
h &= "Mandatory actions:" & gb.NewLine
h &= " --action <ACTION> init | deploy | rollback | status" & gb.NewLine
h &= gb.NewLine
h &= "Options:" & gb.NewLine
h &= " -c --config <FILE> Config (default: /etc/myapp/config.ini)" & gb.NewLine
h &= " -v --verbose <LEVEL> Verbosity 0-3 (default: 0)" & gb.NewLine
h &= " -n --dry-run Dry run" & gb.NewLine
h &= " -V --version Display the version" & gb.NewLine
h &= " -h --help Display this help" & gb.NewLine
h &= gb.NewLine
h &= "Example:" & gb.NewLine
h &= " gbx3 $HOME/MyApp -- -a deploy -v 2 -n -- web01 web02" & gb.NewLine
Return h
End
Usage:
Public Sub Main()
Dim sAction As String
Dim sConfig As String
Dim iVerbosity As Integer
Dim bDryRun As Boolean
Dim bVersion As Boolean
Dim aTargets As String[]
Args.Begin(BuildHelp())
sAction = Args.Get("a", "action", "Action (init|deploy|rollback|status)", "ACTION")
sConfig = Args.Get("c", "config", "Configuration file", "CONFIG", "/etc/myapp/config.ini")
iVerbosity = Args.GetInteger("v", "verbose", "Verbosity level (0-3)", "LEVEL", 0)
bDryRun = Args.Has("n", "dry-run", "Dry run")
bVersion = Args.Has("", "version")
aTargets = Args.End()
Select Case sAction
Case "init"
Print "[INIT] Configuration: " & sConfig
Case "deploy"
Print "[DEPLOY] Target: " & aTargets.Join(", ")
If bDryRun Then Print " (DRY-RUN - no real changes)"
Case "rollback"
Print "[ROLLBACK] Previous version restored"
Case "status"
Print "[STATUS] In progress..."
Case ""
Print "Error: --action is mandatory"
Print "Use -h for help"
Quit 1
Case Else
Print "Error: unknown action '" & sAction & "'"
Quit 1
End Select
Print "Verbosity: " & iVerbosity
End
Private Function BuildHelp() As String
Dim h As String
h &= gb.NewLine
h &= "MyApp v1.2.3 - Deployment manager" & gb.NewLine
h &= gb.NewLine
h &= "Usage: gbx3 /project -- [options] [-- <targets>]" & gb.NewLine
h &= gb.NewLine
h &= "Mandatory actions:" & gb.NewLine
h &= " --action <ACTION> init | deploy | rollback | status" & gb.NewLine
h &= gb.NewLine
h &= "Options:" & gb.NewLine
h &= " -c --config <FILE> Config (default: /etc/myapp/config.ini)" & gb.NewLine
h &= " -v --verbose <LEVEL> Verbosity 0-3 (default: 0)" & gb.NewLine
h &= " -n --dry-run Dry run" & gb.NewLine
h &= " -V --version Display the version" & gb.NewLine
h &= " -h --help Display this help" & gb.NewLine
h &= gb.NewLine
h &= "Example:" & gb.NewLine
h &= " gbx3 $HOME/MyApp -- -a deploy -v 2 -n -- web01 web02" & gb.NewLine
Return h
End
$ gbx3 $HOME/MyApp -- -a deploy -v 2 -n -- web01 web02
[DEPLOY] Target: web01, web02
(DRY-RUN - no real changes)
Verbosity: 2
$ gbx3 $HOME/MyApp -- -a status
[STATUS] In progress...
Verbosity: 0
[DEPLOY] Target: web01, web02
(DRY-RUN - no real changes)
Verbosity: 2
$ gbx3 $HOME/MyApp -- -a status
[STATUS] In progress...
Verbosity: 0
9. Important usage rules
| Point | Detail |
|---|---|
-- separator
| Mandatory between options and raw arguments |
-V/--version
|
Handled automatically, no need for Has()
|
-h/--help
|
Handled automatically, displays the Begin() text
|
| Parsing error | Exits with code 1 automatically |
| Call order |
Begin() → Get/GetFloat/GetInteger/Has() → End()
|
| Missing value |
For Get(): returns "" For GetInteger/GetFloat: returns the default value
|
| Component |
Add gb.args in the .project file
|
10. Quick comparison
| Aspect |
Args (gb)
|
Args (gb.args)
|
|---|---|---|
| Options parsing | ❌ No | ✅ Yes |
| Types (int/float/bool) | ❌ All string | ✅ Typed |
| Default values | ❌ | ✅ |
| Automatic help | ❌ | ✅ |
| Automatic version | ❌ | ✅ |
| Simplicity | ✅ Very simple | ⚠️ More code |
## 📚 The `gb.args` component — Complete guide
@{index}
### [1. Context: two argument levels]
In Gambas, there are **two mechanisms** to receive command line arguments:
#### [A. The `Args` class from the `gb` component (basic)]
[[ code gambas
' Args is a static read-only array
Print Args.Count ' Total number of arguments (includes the program name)
Print Args.Max ' Index of the last argument (= Args.Count - 1)
Print Args.All.Join(" | ") ' All arguments separated by " | "
Print Args[0] ' Program name
Print Args[1] ' First passed argument
]]
**Example:**
[[ code sh
$ gbx3 $HOME/MyApp -- hello world 42
]]
[[ code gambas
Print Args.Count ' → 4
Print Args.Max ' → 3
Print Args.All.Join(" | ") ' → "MyApp | hello | world | 42"
Print Args[0] ' → "MyApp"
Print Args[1] ' → "hello"
Print Args[2] ' → "world"
Print Args[3] ' → "42"
]]
> ⚠️ `Args` from `gb` is **raw**: everything is a string, no options parsing.
#### [B. The `Args` class from the `gb.args` component (sophisticated)]
The `gb.args` component (available since Gambas 3.4) provides a **static** `Args` class with 5 methods to properly parse options and arguments.
### [2. The 5 methods of the `Args` class (gb.args)]
[[
Method
--
Role
==
`Begin([Usage As String])`
--
Starts parsing. Optional: help text
==
`End() As String[]`
--
Ends parsing, returns raw arguments
==
`Get(short, long, desc, argName) As String`
--
String option
==
`GetFloat(short, long[, desc, argName, default]) As Float`
--
Float option
==
`GetInteger(short, long[, desc, argName, default]) As Integer`
--
Integer option
==
`Has(short, long[, desc]) As Boolean`
--
Boolean option (flag)
]]
### [3. Example 1: Minimal program with options]
[[ code gambas
' Main Module (Main)
Public Sub Main()
Args.Begin()
' String option : -f / --file
Dim sFichier As String
sFichier = Args.Get("f", "file", "Input file", "FILE")
' Boolean option (flag) : -v / --verbose
Dim bVerbose As Boolean
bVerbose = Args.Has("v", "verbose")
' Integer option with default value
Dim iTaille As Integer
iTaille = Args.GetInteger("s", "size", "Buffer size", "SIZE", 1024)
' Retrieve the remaining arguments (after --)
Dim aArgs As String[]
aArgs = Args.End()
' Display
Print "File: " & sFichier
Print "Verbose: " & bVerbose
Print "Size: " & iTaille
Print "Remaining arguments: " & aArgs.Join(", ")
End
]]
**Usage:**
[[ code sh
$ gbx3 $HOME/MyApp -- -f config.txt -s 2048 -- input1.txt input2.txt
File: config.txt
Verbose: False
Size: 2048
Remaining arguments: input1.txt, input2.txt
$ gbx3 $HOME/MyApp -- --verbose --file=data.ini -- arg1 arg2 arg3
File: data.ini
Verbose: True
Size: 1024
Remaining arguments: arg1, arg2, arg3
]]
---
### [4. Example 2: With complete help text]
[[ code gambas
Public Sub Main()
Dim sMode As String
Dim fRatio As Float
Dim bForce As Boolean
Dim aArgs As String[]
Args.Begin(SetHelpText())
sMode = Args.Get("m", "mode", "Processing mode (fast|normal|deep)", "MODE")
fRatio = Args.GetFloat("r", "ratio", "Compression ratio", "RATIO", 0.75)
bForce = Args.Has("f", "force", "Force processing without confirmation")
aArgs = Args.End()
Print "Mode: " & sMode
Print "Ratio: " & fRatio
Print "Force: " & bForce
Print "Args: " & aArgs.Join(", ")
End
Private Function SetHelpText() As String
Dim sText As String
sText &= gb.NewLine
sText &= "MyApp - Image processing" & gb.NewLine
sText &= gb.NewLine
sText &= "Usage: gbx3 /path/to/project -- [options] [-- <args>]" & gb.NewLine
sText &= gb.NewLine
sText &= "Example: gbx3 $HOME/MyApp -- -m deep -r 0.5 -- img1.png img2.png" & gb.NewLine
sText &= gb.NewLine
sText &= "Options:" & gb.NewLine
sText &= " -m --mode <MODE> Processing mode (fast|normal|deep)" & gb.NewLine
sText &= " -r --ratio <RATIO> Compression ratio (default: 0.75)" & gb.NewLine
sText &= " -f --force Force processing" & gb.NewLine
sText &= " -V --version Display the version" & gb.NewLine
sText &= " -h --help Display this help" & gb.NewLine
Return sText
End
]]
**`--help` output:**
[[ code sh
MyApp - Image processing
Usage: gbx3 /path/to/project -- [options] [-- <args>]
Example: gbx3 $HOME/MyApp -- -m deep -r 0.5 -- img1.png img2.png
Options:
-m --mode <MODE> Processing mode (fast|normal|deep)
-r --ratio <RATIO> Compression ratio (default: 0.75)
-f --force Force processing
-V --version Display the version
-h --help Display this help
]]
### [5. Example 3: Options with default values and multiple types]
[[ code gambas
Public Sub Main()
Dim sHost As String
Dim iPort As Integer
Dim fTimeout As Float
Dim bDebug As Boolean
Dim bQuiet As Boolean
Dim aUrls As String[]
Args.Begin("MyApp - HTTP Client")
' String with default
sHost = Args.Get("h", "host", "Target server", "HOST", "localhost")
' Integer with default
iPort = Args.GetInteger("p", "port", "Server port", "PORT", 8080)
' Float with default
fTimeout = Args.GetFloat("t", "timeout", "Timeout in seconds", "TIMEOUT", 30.0)
' Boolean flags
bDebug = Args.Has("d", "debug")
bQuiet = Args.Has("q", "quiet")
' Remaining arguments (URLs)
aUrls = Args.End()
If Not bQuiet Then
Print "Connecting to " & sHost & ":" & iPort
Print "Timeout: " & fTimeout & "s"
Print "Debug: " & bDebug
Print "URLs: " & aUrls.Join(", ")
Endif
End
]]
**Usages:**
[[ code sh
# With all default options
$ gbx3 $HOME/MyApp -- --host api.example.com --port 443 -- https://api.example.com/data
Connecting to api.example.com:443
Timeout: 30.0s
Debug: False
URLs: https://api.example.com/data
# With flags and custom values
$ gbx3 $HOME/MyApp -- -d -t 60.5 -- https://api1.com https://api2.com
Connecting to localhost:8080
Timeout: 60.5s
Debug: True
URLs: https://api1.com, https://api2.com
]]
### [6. Example 4: Option without value (flag) + option with mandatory value]
[[ code gambas
Public Sub Main()
Dim sOutput As String
Dim bList As Boolean
Dim bVersion As Boolean
Dim aFiles As String[]
Args.Begin("MyApp - File manager")
' Option with mandatory value (no default)
sOutput = Args.Get("o", "output", "Output file", "FILE")
' Flag (boolean)
bList = Args.Has("l", "list", "List files")
' Note: -V and -h are handled automatically by gb.args
aFiles = Args.End()
If bList Then
Print "File list:"
Print aFiles.Join(gb.NewLine)
Else
Print "Output to: " & sOutput
Endif
End
]]
**Usage:**
[[ code sh
# Mandatory -o option
$ gbx3 $HOME/MyApp -- -o result.txt file1.txt file2.txt
Output to: result.txt
# -l flag
$ gbx3 $HOME/MyApp -- -l -- file1.txt file2.txt
File list:
file1.txt
file2.txt
# Version (handled automatically)
$ gbx3 $HOME/MyApp -- --version
0.1.0
# Help (handled automatically)
$ gbx3 $HOME/MyApp -- -h
MyApp - File manager
Usage: gbx3 /path/to/project -- [options] [-- <args>]
Options:
-o --output <FILE> Output file
-l --list List files
-V --version Display the version
-h --help Display this help
]]
### [7. Example 5: Error handling]
[[ code gambas
Public Sub Main()
Try
Args.Begin(SetHelpText())
Dim sMode As String
sMode = Args.Get("m", "mode", "Mode (fast|normal|deep)", "MODE")
' Default value if option not specified
If sMode = "" Then
sMode = "normal"
Endif
Args.End()
Print "Selected mode: " & sMode
Catch
' gb.args exits with code 1 in case of a parsing error
' (unknown option, missing value, etc.)
Print "Command line error: " & Error.Text
Quit 1
End
End
]]
**Common errors:**
[[ code sh
# Unknown option → exits with code 1
$ gbx3 $HOME/MyApp -- -z badoption
gb.args: unknown option 'z'
# Option with missing value → exits with code 1
$ gbx3 $HOME/MyApp -- -m
gb.args: option 'm' requires an argument
# -o option without value → default value = ""
$ gbx3 $HOME/MyApp -- --output
Output to: (empty)
]]
### [8. Example 6: Complete professional CLI program]
[[ code gambas
' Main Module
Public Sub Main()
Dim sAction As String
Dim sConfig As String
Dim iVerbosity As Integer
Dim bDryRun As Boolean
Dim bVersion As Boolean
Dim aTargets As String[]
Args.Begin(BuildHelp())
sAction = Args.Get("a", "action", "Action (init|deploy|rollback|status)", "ACTION")
sConfig = Args.Get("c", "config", "Configuration file", "CONFIG", "/etc/myapp/config.ini")
iVerbosity = Args.GetInteger("v", "verbose", "Verbosity level (0-3)", "LEVEL", 0)
bDryRun = Args.Has("n", "dry-run", "Dry run")
bVersion = Args.Has("", "version")
aTargets = Args.End()
Select Case sAction
Case "init"
Print "[INIT] Configuration: " & sConfig
Case "deploy"
Print "[DEPLOY] Target: " & aTargets.Join(", ")
If bDryRun Then Print " (DRY-RUN - no real changes)"
Case "rollback"
Print "[ROLLBACK] Previous version restored"
Case "status"
Print "[STATUS] In progress..."
Case ""
Print "Error: --action is mandatory"
Print "Use -h for help"
Quit 1
Case Else
Print "Error: unknown action '" & sAction & "'"
Quit 1
End Select
Print "Verbosity: " & iVerbosity
End
Private Function BuildHelp() As String
Dim h As String
h &= gb.NewLine
h &= "MyApp v1.2.3 - Deployment manager" & gb.NewLine
h &= gb.NewLine
h &= "Usage: gbx3 /project -- [options] [-- <targets>]" & gb.NewLine
h &= gb.NewLine
h &= "Mandatory actions:" & gb.NewLine
h &= " --action <ACTION> init | deploy | rollback | status" & gb.NewLine
h &= gb.NewLine
h &= "Options:" & gb.NewLine
h &= " -c --config <FILE> Config (default: /etc/myapp/config.ini)" & gb.NewLine
h &= " -v --verbose <LEVEL> Verbosity 0-3 (default: 0)" & gb.NewLine
h &= " -n --dry-run Dry run" & gb.NewLine
h &= " -V --version Display the version" & gb.NewLine
h &= " -h --help Display this help" & gb.NewLine
h &= gb.NewLine
h &= "Example:" & gb.NewLine
h &= " gbx3 $HOME/MyApp -- -a deploy -v 2 -n -- web01 web02" & gb.NewLine
Return h
End
]]
**Usage:**
[[ code sh
$ gbx3 $HOME/MyApp -- -a deploy -v 2 -n -- web01 web02
[DEPLOY] Target: web01, web02
(DRY-RUN - no real changes)
Verbosity: 2
$ gbx3 $HOME/MyApp -- -a status
[STATUS] In progress...
Verbosity: 0
]]
### [9. Important usage rules]
[[
Point
--
Detail
==
**`--` separator**
--
Mandatory between options and raw arguments
==
**`-V/--version`**
--
Handled automatically, no need for `Has()`
==
**`-h/--help`**
--
Handled automatically, displays the `Begin()` text
==
**Parsing error**
--
Exits with code 1 automatically
==
**Call order**
--
`Begin()` → `Get/GetFloat/GetInteger/Has()` → `End()`
==
**Missing value**
--
For `Get()`: returns `""` \
For `GetInteger/GetFloat`: returns the default value
==
**Component**
--
Add `gb.args` in the `.project` file
]]
### [10. Quick comparison]
[[
Aspect
--
`Args` (gb)
--
`Args` (gb.args)
==
Options parsing
--
❌ No
--
✅ Yes
==
Types (int/float/bool)
--
❌ All string
--
✅ Typed
==
Default values
--
❌
--
✅
==
Automatic help
--
❌
--
✅
==
Automatic version
--
❌
--
✅
==
Simplicity
--
✅ Very simple
--
⚠️ More code
]]
| Re: Documentation of gb.args and gb.highlight - Gambas | Benoît Minisini <benoit.minisini@xxxxxxxxxxxxxxxx> |