GNAT.Command_Line 中的选项参数问题
Issue with option arguments in GNAT.Command_Line
我在使用 GNAT.Command_Line
包解析 Ada 中的输入参数时遇到问题。我已经根据 this Ada Gem as well as this answer 等资源对我的方法进行了建模,但似乎无法使参数接受开关正常工作。
main.adb
:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Command_Line; use Command_Line;
procedure Main is
CLS : Command_Line_State;
begin
Parse_Command_Line (State => CLS);
end Main;
Command_Line.ads
:
with Ada.Containers.Vectors; use Ada.Containers;
with Ada.Directories; use Ada.Directories;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Gnat.Command_Line; use Gnat.Command_Line;
with Gnat.OS_Lib; use Gnat.OS_Lib;
with Gnat.Strings; use Gnat.Strings;
package Command_Line is
type Output_Type is (CSV, TXT);
type Filename_Record is record
Was_Given : Boolean;
Filename : Unbounded_String;
Path : Unbounded_String;
end record;
package Filename_Vectors is new Vectors (Positive, Filename_Record);
type Command_Line_State is record
Filenames : Filename_Vectors.Vector;
Interactive_Mode : Boolean := False;
Output_Format : Output_Type;
end record;
procedure Parse_Command_Line (State : in out Command_Line_State);
end Command_Line;
Command_Line.adb
:
package body Command_Line is
procedure Parse_Command_Line(State : in out Command_Line_State) is
Configuration : Command_Line_Configuration;
In_Path : aliased Gnat.Strings.String_Access;
Out_Path : aliased Gnat.Strings.String_Access;
Interactive : aliased Boolean := False;
CSV_Format : aliased Boolean := False;
begin
Define_Switch (Config => Configuration,
Output => In_Path'Access,
Switch => "-i",
Long_Switch => "--inpath",
Help => "Supplies an external path for case files not colocated with the program",
Argument => "PATH");
Define_Switch (Config => Configuration,
Output => Out_Path'Access,
Switch => "-o",
Long_Switch => "--outpath",
Help => "Identifies an external path or directory to write output data to",
Argument => "PATH");
Define_Switch (Config => Configuration,
Output => Interactive'Access,
Switch => "-n",
Long_Switch => "--interactive",
Help => "Places program into interactive mode");
Define_Switch (Config => Configuration,
Output => CSV_Format'Access,
Switch => "-c",
Long_Switch => "--csv",
Help => "Output data in CSV, rather than TXT format");
Getopt (Configuration);
declare
In_Path_Unbounded : Unbounded_String := To_Unbounded_String (In_Path.all);
Out_Path_Unbounded : Unbounded_String := To_Unbounded_String (Out_Path.all);
begin
Put_Line ("Input file path: '" & To_String (In_Path_Unbounded) & "'.");
Put_Line ("Output file path: '" & To_String (Out_Path_Unbounded) & "'.");
end;
if Interactive then
Put_Line ("Interactive mode (-n, --interactive) was set to: True.");
else
Put_Line ("Interactive mode (-n, --interactive) was set to: False.");
end if;
if CSV_Format then
Put_Line ("CSV formatting mode (-c, --csv) was set to: True.");
else
Put_Line ("CSV formatting mode (-c, --csv) was set to: False.");
end if;
end Parse_Command_Line;
end Command_Line;
请注意,某些结构存在于最终用途应用程序中。当我 运行 从 PowerShell window 使用以下选项的程序时:
.\main.exe -i INPATH -o OUTPATH -n -c
我得到以下结果:
Input file path: ''.
Output file path: ''.
Interactive mode (-n, --interactive) was set to: True.
CSV formatting mode (-c, --csv) was set to: True.
如何修改现有代码,以便 Getopt
解析器和 GNAT.Command_Line
正确捕获字符串接受选项的参数(即 INPATH
和 OUTPATH
) ?
诀窍是为 Switch
和 Long_Switch
参数添加适当的字符。
在 g-comlin.ads
中,Define_Switch
的描述如下(另见 here):
procedure Define_Switch
(Config : in out Command_Line_Configuration;
Switch : String := "";
Long_Switch : String := "";
Help : String := "";
Section : String := "";
Argument : String := "ARG");
-- Indicates a new switch. The format of this switch follows the getopt
-- format (trailing ':', '?', etc for defining a switch with parameters).
虽然 getopt
的描述为(在同一文件中,另请参阅 here):
-- Switches is a string of all the possible switches, separated by
-- spaces. A switch can be followed by one of the following characters:
--
-- ':' The switch requires a parameter. There can optionally be a space
-- on the command line between the switch and its parameter.
--
-- '=' The switch requires a parameter. There can either be a '=' or a
-- space on the command line between the switch and its parameter.
--
-- '!' The switch requires a parameter, but there can be no space on the
-- command line between the switch and its parameter.
--
-- '?' The switch may have an optional parameter. There can be no space
-- between the switch and its argument.
因此,在 Switch
和 Long_Switch
的参数中添加冒号 (:
) 即可。例如:
Define_Switch (Config => Configuration,
Output => In_Path'Access,
Switch => "-i:", -- <<< !!!
Long_Switch => "--inpath:", -- <<< !!!
Help => "Supplies an external path for case files not colocated with the program",
Argument => "PATH");
为 -i
和 -o
调整 Switch
和 Long_Switch
参数现在将给出所需的结果:
$ ./obj/main -i "Foo" -o "Bar" -n -c
Input file path: 'Foo'.
Output file path: 'Bar'.
Interactive mode (-n, --interactive) was set to: True.
CSV formatting mode (-c, --csv) was set to: True.
我在使用 GNAT.Command_Line
包解析 Ada 中的输入参数时遇到问题。我已经根据 this Ada Gem as well as this answer 等资源对我的方法进行了建模,但似乎无法使参数接受开关正常工作。
main.adb
:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Command_Line; use Command_Line;
procedure Main is
CLS : Command_Line_State;
begin
Parse_Command_Line (State => CLS);
end Main;
Command_Line.ads
:
with Ada.Containers.Vectors; use Ada.Containers;
with Ada.Directories; use Ada.Directories;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Gnat.Command_Line; use Gnat.Command_Line;
with Gnat.OS_Lib; use Gnat.OS_Lib;
with Gnat.Strings; use Gnat.Strings;
package Command_Line is
type Output_Type is (CSV, TXT);
type Filename_Record is record
Was_Given : Boolean;
Filename : Unbounded_String;
Path : Unbounded_String;
end record;
package Filename_Vectors is new Vectors (Positive, Filename_Record);
type Command_Line_State is record
Filenames : Filename_Vectors.Vector;
Interactive_Mode : Boolean := False;
Output_Format : Output_Type;
end record;
procedure Parse_Command_Line (State : in out Command_Line_State);
end Command_Line;
Command_Line.adb
:
package body Command_Line is
procedure Parse_Command_Line(State : in out Command_Line_State) is
Configuration : Command_Line_Configuration;
In_Path : aliased Gnat.Strings.String_Access;
Out_Path : aliased Gnat.Strings.String_Access;
Interactive : aliased Boolean := False;
CSV_Format : aliased Boolean := False;
begin
Define_Switch (Config => Configuration,
Output => In_Path'Access,
Switch => "-i",
Long_Switch => "--inpath",
Help => "Supplies an external path for case files not colocated with the program",
Argument => "PATH");
Define_Switch (Config => Configuration,
Output => Out_Path'Access,
Switch => "-o",
Long_Switch => "--outpath",
Help => "Identifies an external path or directory to write output data to",
Argument => "PATH");
Define_Switch (Config => Configuration,
Output => Interactive'Access,
Switch => "-n",
Long_Switch => "--interactive",
Help => "Places program into interactive mode");
Define_Switch (Config => Configuration,
Output => CSV_Format'Access,
Switch => "-c",
Long_Switch => "--csv",
Help => "Output data in CSV, rather than TXT format");
Getopt (Configuration);
declare
In_Path_Unbounded : Unbounded_String := To_Unbounded_String (In_Path.all);
Out_Path_Unbounded : Unbounded_String := To_Unbounded_String (Out_Path.all);
begin
Put_Line ("Input file path: '" & To_String (In_Path_Unbounded) & "'.");
Put_Line ("Output file path: '" & To_String (Out_Path_Unbounded) & "'.");
end;
if Interactive then
Put_Line ("Interactive mode (-n, --interactive) was set to: True.");
else
Put_Line ("Interactive mode (-n, --interactive) was set to: False.");
end if;
if CSV_Format then
Put_Line ("CSV formatting mode (-c, --csv) was set to: True.");
else
Put_Line ("CSV formatting mode (-c, --csv) was set to: False.");
end if;
end Parse_Command_Line;
end Command_Line;
请注意,某些结构存在于最终用途应用程序中。当我 运行 从 PowerShell window 使用以下选项的程序时:
.\main.exe -i INPATH -o OUTPATH -n -c
我得到以下结果:
Input file path: ''.
Output file path: ''.
Interactive mode (-n, --interactive) was set to: True.
CSV formatting mode (-c, --csv) was set to: True.
如何修改现有代码,以便 Getopt
解析器和 GNAT.Command_Line
正确捕获字符串接受选项的参数(即 INPATH
和 OUTPATH
) ?
诀窍是为 Switch
和 Long_Switch
参数添加适当的字符。
在 g-comlin.ads
中,Define_Switch
的描述如下(另见 here):
procedure Define_Switch
(Config : in out Command_Line_Configuration;
Switch : String := "";
Long_Switch : String := "";
Help : String := "";
Section : String := "";
Argument : String := "ARG");
-- Indicates a new switch. The format of this switch follows the getopt
-- format (trailing ':', '?', etc for defining a switch with parameters).
虽然 getopt
的描述为(在同一文件中,另请参阅 here):
-- Switches is a string of all the possible switches, separated by
-- spaces. A switch can be followed by one of the following characters:
--
-- ':' The switch requires a parameter. There can optionally be a space
-- on the command line between the switch and its parameter.
--
-- '=' The switch requires a parameter. There can either be a '=' or a
-- space on the command line between the switch and its parameter.
--
-- '!' The switch requires a parameter, but there can be no space on the
-- command line between the switch and its parameter.
--
-- '?' The switch may have an optional parameter. There can be no space
-- between the switch and its argument.
因此,在 Switch
和 Long_Switch
的参数中添加冒号 (:
) 即可。例如:
Define_Switch (Config => Configuration,
Output => In_Path'Access,
Switch => "-i:", -- <<< !!!
Long_Switch => "--inpath:", -- <<< !!!
Help => "Supplies an external path for case files not colocated with the program",
Argument => "PATH");
为 -i
和 -o
调整 Switch
和 Long_Switch
参数现在将给出所需的结果:
$ ./obj/main -i "Foo" -o "Bar" -n -c
Input file path: 'Foo'.
Output file path: 'Bar'.
Interactive mode (-n, --interactive) was set to: True.
CSV formatting mode (-c, --csv) was set to: True.