diff --git a/Makefile b/Makefile index 37c831fb..7b6a61e8 100644 --- a/Makefile +++ b/Makefile @@ -193,6 +193,7 @@ misc: # Check compilation of other projects gprbuild $(GPRBUILD_FLAGS) -aPgnat gnat/tools/json_schema.gpr gprbuild $(GPRBUILD_FLAGS) -aPgnat examples/regexp/grep.gpr gprbuild $(GPRBUILD_FLAGS) examples/blogs/json_1/blog_1.gpr + gprbuild $(GPRBUILD_FLAGS) examples/command_line/command/command_line_command.gpr spellcheck: @STATUS=0; \ diff --git a/examples/command_line/command/command_line_command.adb b/examples/command_line/command/command_line_command.adb new file mode 100644 index 00000000..b21684e0 --- /dev/null +++ b/examples/command_line/command/command_line_command.adb @@ -0,0 +1,106 @@ + +with VSS.Application; +with VSS.Command_Line.Parsers; +with VSS.Strings.Formatters.Strings; +with VSS.Strings.Templates; +with VSS.Text_Streams.Standards; + +procedure Command_Line_Command is + + use type VSS.Strings.Virtual_String; + + Parser : VSS.Command_Line.Parsers.Command_Line_Parser; + Global_Help_Option : constant VSS.Command_Line.Binary_Option := + (Short_Name => "h", + Long_Name => "help", + Description => "Display help information"); + Global_Verbose_Option : constant VSS.Command_Line.Binary_Option := + (Short_Name => "v", + Long_Name => "verbose", + Description => "Verbose output"); + Command_Option : constant VSS.Command_Line.Positional_Option := + (Name => "", + Description => "Command to be executed: info, list"); + + List_Long_Option : constant VSS.Command_Line.Binary_Option := + (Short_Name => "l", + Long_Name => "long", + Description => "Enable long output format"); + + Info_Advanced_Option : constant VSS.Command_Line.Binary_Option := + (Short_Name => "a", + Long_Name => "advanced", + Description => "Advanced output"); + + Output : VSS.Text_Streams.Output_Text_Stream'Class := + VSS.Text_Streams.Standards.Standard_Output; + Success : Boolean := True; + +begin + -- Add global options + + Parser.Add_Option (Global_Help_Option); + Parser.Add_Option (Global_Verbose_Option); + Parser.Add_Option (Command_Option); + + -- Parse command line to get command name. + + if not Parser.Parse (VSS.Application.Arguments) then + VSS.Command_Line.Report_Error (Parser.Error_Message); + end if; + + -- Add command's options when command is specified, report error for + -- unknown command. + + if not Parser.Is_Specified (Command_Option) then + if not Parser.Is_Specified (Global_Help_Option) then + VSS.Command_Line.Report_Error ("no command specified"); + end if; + + elsif Parser.Value (Command_Option) = "info" then + Parser.Add_Option (Info_Advanced_Option); + + elsif Parser.Value (Command_Option) = "list" then + Parser.Add_Option (List_Long_Option); + + else + VSS.Command_Line.Report_Error + (VSS.Strings.Templates.To_Virtual_String_Template + ("unknown command: '{}'").Format + (VSS.Strings.Formatters.Strings.Image + (Parser.Value (Command_Option)))); + end if; + + -- Reparse command line + + if not Parser.Parse (VSS.Application.Arguments) then + VSS.Command_Line.Report_Error (Parser.Error_Message); + end if; + + -- Process help option + + if Parser.Is_Specified (Global_Help_Option) then + VSS.Command_Line.Report_Error (Parser.Help_Text); + end if; + + -- Report unknown options + + if not Parser.Unknown_Option_Arguments.Is_Empty then + VSS.Command_Line.Report_Error + (VSS.Strings.Templates.To_Virtual_String_Template + ("unknown option: '{}'").Format + (VSS.Strings.Formatters.Strings.Image + (Parser.Unknown_Option_Arguments.First_Element))); + end if; + + -- Execute command + + if Parser.Value (Command_Option) = "info" then + Output.Put_Line ("Some information", Success); + + elsif Parser.Value (Command_Option) = "list" then + for Name of Parser.Positional_Arguments loop + Output.Put_Line (Name, Success); + end loop; + end if; +end Command_Line_Command; diff --git a/examples/command_line/command/command_line_command.gpr b/examples/command_line/command/command_line_command.gpr new file mode 100644 index 00000000..8bcb92bb --- /dev/null +++ b/examples/command_line/command/command_line_command.gpr @@ -0,0 +1,12 @@ +with "vss_text"; + +project Command_Line_Command is + + for Object_Dir use ".objs"; + for Main use ("command_line_command.adb"); + + package Compiler is + for Switches ("Ada") use ("-g", "-gnatW8", "-gnat2022"); + end Compiler; + +end Command_Line_Command; diff --git a/source/os/implementation/vss-command_line-parsers.adb b/source/os/implementation/vss-command_line-parsers.adb index d7f3d1aa..a1ada278 100644 --- a/source/os/implementation/vss-command_line-parsers.adb +++ b/source/os/implementation/vss-command_line-parsers.adb @@ -353,6 +353,12 @@ package body VSS.Command_Line.Parsers is Success : Boolean := True; begin + Self.Error_Message.Clear; + Self.Known_Named_Options_Values.Clear; + Self.Unknown_Named_Options_Values.Clear; + Self.Positional_Options_Values.Clear; + Self.Only_Positional := False; + while Index <= Arguments.Length loop Self.Parse_Argument (Arguments, Index, Success); diff --git a/source/os/implementation/vss-command_line.adb b/source/os/implementation/vss-command_line.adb index 57689927..ba8585cc 100644 --- a/source/os/implementation/vss-command_line.adb +++ b/source/os/implementation/vss-command_line.adb @@ -145,6 +145,19 @@ package body VSS.Command_Line is GNAT.OS_Lib.OS_Exit (1); end Report_Error; + ------------------ + -- Report_Error -- + ------------------ + + procedure Report_Error + (Message : VSS.String_Vectors.Virtual_String_Vector) is + begin + Platform.Report_Message + (Message => Message, + Is_Error => True); + GNAT.OS_Lib.OS_Exit (1); + end Report_Error; + ----------------- -- Unique_Name -- ----------------- diff --git a/source/os/vss-command_line.ads b/source/os/vss-command_line.ads index 52fb5457..1c41415e 100644 --- a/source/os/vss-command_line.ads +++ b/source/os/vss-command_line.ads @@ -84,6 +84,10 @@ package VSS.Command_Line is with No_Return; -- Report error and terminate application. + procedure Report_Error (Message : VSS.String_Vectors.Virtual_String_Vector) + with No_Return; + -- Report error and terminate application. + private function Unique_Name