GNU GetOpt
Table of Contents
Package | Available Assertions |
---|---|
AdaCL.Command_Line.GetOpt | GNU GetOpt style command line parser with wide character support |
A modern object oriented version of GetOpt made for Ada - that’s without the C style ugliness.
Also, unlike for example GNAT.Command_Line this package is re-entrant. All internal states are kept inside the class instance so two tasks can parse the command line in parallel.
Last not least this command line parser has wide character support for short options, long options and file names.
Specifying parser. #
Since the parser is object oriented and re-entrant using it take a bit more effort of creating a child class to perform the parsing operation.
type Object is new AdaCL.Command_Line.GetOpt.Object with private;
overriding procedure Parse (This : in out Object);
overriding procedure WriteHelp (This : in out Object);
overriding procedure Analyze_WithoutArgument (This : in out Object);
overriding procedure Analyze_WithArgument (This : in out Object);
overriding procedure Analyze_GNU (This : in out Object);
overriding procedure Analyze_File (This : in out Object);
private
package Inherited renames AdaCL.Command_Line.GetOpt;
type Object is new Inherited.Object with record
Operation : Operation_Type := None;
In_File : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
Out_File : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
With_Code : Boolean := True;
Quotes : Quotes_Type := HP;
end record;
Implementing a parser #
Most command line parser are based around a loop and a huge case but AdaCL.Command_Line.GetOpt
is object orientated
and based around overriding procedures.
Parse #
Override Parse
to set the parameter you wish to use for the scan. At least the pattern for short options need to be set.
Decode_Long : constant Wide_Wide_String := "decode";
Decode_Short : constant Wide_Wide_Character := 'd';
Encode_Long : constant Wide_Wide_String := "encode";
Encode_Short : constant Wide_Wide_Character := 'e';
Quotes_Long : constant Wide_Wide_String := "quotes";
Quotes_Short : constant Wide_Wide_Character := 'q';
Quotes_HP : constant Wide_Wide_String := "hp";
Quotes_Single : constant Wide_Wide_String := "single";
Quotes_Double : constant Wide_Wide_String := "double";
Quotes_Back : constant Wide_Wide_String := "back";
Pattern : constant Wide_Wide_String :=
[GetOpt.Option_Error,
Decode_Short,
Encode_Short,
Quotes_Short,
GetOpt.Option_Argument];
overriding procedure Parse (This : in out Object) is
Super : Inherited.Object renames Inherited.Object (This);
begin
This.Set_Pattern (Pattern);
This.Set_ExceptionOnError (True);
This.Set_ExtractGNU (True);
Super.Parse;
return;
end Parse
WriteHelp #
Use WriteHelp
to write help informations when the user uses the -h
or --help
options.
overriding procedure WriteHelp (This : in out Object) is
pragma Debug (AdaCL.Trace.Entering (AdaCL.Trace.Parameter & This'Image));
use Ada.Text_IO;
use GetOpt;
Super : Inherited.Object renames Inherited.Object (This);
begin
New_Line;
Put_Line ("hp41cx_tools-main:");
New_Line;
Put_Line (" PX-41CX memory dump tool");
New_Line;
Put_Line ("Usage:");
New_Line;
Put_Line (" hp41cx_tools-main [command] in_file out_file");
New_Line;
Put_Line ("Commands:");
New_Line;
Put_Help_Line (Decode_Short, Decode_Long, "Decode PX-41CX memory dump to source code.");
Put_Help_Line (Encode_Short, Encode_Long, "Encode PX-41CX source code to memory dump.");
New_Line;
Put_Line ("General options:");
New_Line;
Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_HP, "Use HP-41CX style quotes (⊤) for alpha strings.");
Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_Single, "Use single quote (') for alpha strings.");
Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_Double, "Use double quote ("") for alpha strings.");
Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_Back, "Use backicks (`) for alpha strings.");
New_Line;
Put_Line ("Other options:");
New_Line;
Put_Line
("Version " & Hp41cx_Tools_Config.Crate_Version &
" (https://calculator-scripts.sourceforge.io/hp41cx-tools/).");
New_Line;
Super.WriteHelp;
pragma Debug (AdaCL.Trace.Exiting);
return;
end WriteHelp;
The call to Super.WriteHelp;
will print the help for the common options like --help
/-h
and --verbose
/-h
.
Analyze_WithoutArgument #
The Analyze_WithoutArgument
procedure analyses short options without extra arguments.
overriding procedure Analyze_WithoutArgument (This : in out Object) is
Super : Inherited.Object renames Inherited.Object (This);
Option : constant Wide_Wide_Character := This.Get_Option;
begin
if Option = Decode_Short then
This.Check_Command_None;
This.Operation := Decode;
elsif Option = Encode_Short then
This.Check_Command_None;
This.Operation := Encode;
else
Super.Analyze_WithoutArgument;
end if;
return;
end Analyze_WithoutArgument;
The call to Super.Analyze_WithArgument;
will analyse the common options like -h
and -v
.
Analyze_WithArgument #
The Analyze_WithoutArgument
procedure analyses short options with extra arguments.
overriding procedure Analyze_WithArgument (This : in out Object) is
Super : Inherited.Object renames Inherited.Object (This);
Option : constant Wide_Wide_Character := This.Get_Option;
Argument : constant Wide_Wide_String := This.Get_Argument;
begin
if Option = Quotes_Short then
This.Set_Quotes (Argument);
else
Super.Analyze_WithArgument;
end if;
return;
end Analyze_WithArgument;
Analyze_GNU #
The Analyze_WithoutArgument
procedure analyses long options with or without extra arguments.
overriding procedure Analyze_GNU (This : in out Object) is
Super : Inherited.Object renames Inherited.Object (This);
Option : constant Wide_Wide_String := This.Get_GNUOption;
Argument : constant Wide_Wide_String := This.Get_Argument;
begin
if Option = Decode_Long then
This.Check_Command_None;
This.Operation := Decode;
elsif Option = Encode_Long then
This.Check_Command_None;
This.Operation := Encode;
elsif Option = Quotes_Long then
This.Set_Quotes (Argument);
else
Super.Analyze_GNU;
end if;
return;
end Analyze_GNU;
The call to Super.Analyze_GNU;
will analyse the common options like --help
and --verbose
.
Analyze_File #
The Analyze_File
processes all file names or other text which is not part of any option.
overriding procedure Analyze_File (This : in out Object) is
Super : Inherited.Object renames Inherited.Object (This);
Argument : constant Wide_Wide_String := This.Get_Argument;
begin
Super.Analyze_File;
if This.In_File = Ada.Strings.Unbounded.Null_Unbounded_String then
This.In_File := Unbounded.To_Unbounded_String (AdaCL.To_UTF_String (Argument));
elsif This.Out_File = Ada.Strings.Unbounded.Null_Unbounded_String then
This.Out_File := Unbounded.To_Unbounded_String (AdaCL.To_UTF_String (Argument));
end if;
return;
end Analyze_File;
Executing the parser. #
The actuall parsing
Try :
declare
Options : CommandLine.Object;
begin
Options.Parse;
-- Options should now contains all the parsed options and filenames.
exception
when AnException : GetOpt.Option_Parse_Error =>
-- command line error handler.
when AnException : others =>
-- other error handler
end Try;
Examples: #
- AdaCL.Trace
- Simple parser to mange the trace setting in procedure
Initialize
- HP41CX_Tools.Commandline
- Full features parser for HP-41CX emulator Tools.
- Atr_Tools.CommandLine
- Full features parser for Atari / SIO2PC tools for ATR-files
- Check_EXE.CommandLine
- Full features parser for Atari tools for for handling EXE-files