diff --git a/example/src/clic_ex-commands-subsub.adb b/example/src/clic_ex-commands-subsub.adb index 714e994..77b2fd3 100644 --- a/example/src/clic_ex-commands-subsub.adb +++ b/example/src/clic_ex-commands-subsub.adb @@ -23,11 +23,11 @@ package body CLIC_Ex.Commands.Subsub is Put_Line => Ada.Text_IO.Put_Line, Put_Error => Ada.Text_IO.Put_Line, Error_Exit => GNAT.OS_Lib.OS_Exit, - TTY_Chapter => CLIC.TTY.Info, - TTY_Description => CLIC.TTY.Description, - TTY_Version => CLIC.TTY.Version, - TTY_Underline => CLIC.TTY.Underline, - TTY_Emph => CLIC.TTY.Emph); + TTY_Chapter => CLIC.Formatter.Chapter, + TTY_Description => CLIC.Formatter.Description, + TTY_Version => CLIC.Formatter.Version, + TTY_Underline => CLIC.Formatter.Underline, + TTY_Emph => CLIC.Formatter.Emph); begin Sub.Register (new Sub.Builtin_Help); Sub.Register (new CLIC_Ex.Commands.TTY.Instance); diff --git a/example/src/clic_ex-commands.adb b/example/src/clic_ex-commands.adb index 247d6a2..7552c48 100644 --- a/example/src/clic_ex-commands.adb +++ b/example/src/clic_ex-commands.adb @@ -1,6 +1,6 @@ with AAA.Strings; -with CLIC.TTY; +with CLIC.Formatter; with CLIC.User_Input; with CLIC.Config.Load; @@ -22,6 +22,9 @@ package body CLIC_Ex.Commands is No_TTY : aliased Boolean := False; -- Used to disable control characters in output + Markdown_Help : aliased Boolean := False; + -- Used to enable help display in markdown format + ------------------------- -- Set_Global_Switches -- ------------------------- @@ -50,6 +53,13 @@ package body CLIC_Ex.Commands is No_TTY'Access, Long_Switch => "--no-tty", Help => "Disables control characters in output"); + + Define_Switch (Config, + Markdown_Help'Access, + Long_Switch => "--markdown", + Help => + "Enables output of markdown format for help"); + end Set_Global_Switches; ------------- @@ -61,11 +71,15 @@ package body CLIC_Ex.Commands is Sub_Cmd.Parse_Global_Switches; if No_TTY then - CLIC.TTY.Force_Disable_TTY; + CLIC.Formatter.Force_Disable_TTY; + end if; + + if Markdown_Help then + CLIC.Formatter.Enable_Markdown; end if; if not No_Color and then not No_TTY then - CLIC.TTY.Enable_Color (Force => False); + CLIC.Formatter.Enable_Color (Force => False); -- This may still not enable color if TTY is detected to be incapable end if; diff --git a/example/src/clic_ex-commands.ads b/example/src/clic_ex-commands.ads index a670a07..e79a83b 100644 --- a/example/src/clic_ex-commands.ads +++ b/example/src/clic_ex-commands.ads @@ -2,7 +2,7 @@ private with Ada.Text_IO; private with GNAT.OS_Lib; private with CLIC.Subcommand.Instance; -private with CLIC.TTY; +private with CLIC.Formatter; private with CLIC.Config; package CLIC_Ex.Commands is @@ -24,9 +24,9 @@ private Put_Line => Ada.Text_IO.Put_Line, Put_Error => Ada.Text_IO.Put_Line, Error_Exit => GNAT.OS_Lib.OS_Exit, - TTY_Chapter => CLIC.TTY.Info, - TTY_Description => CLIC.TTY.Description, - TTY_Version => CLIC.TTY.Version, - TTY_Underline => CLIC.TTY.Underline, - TTY_Emph => CLIC.TTY.Emph); + TTY_Chapter => CLIC.Formatter.Chapter, + TTY_Description => CLIC.Formatter.Description, + TTY_Version => CLIC.Formatter.Version, + TTY_Underline => CLIC.Formatter.Underline, + TTY_Emph => CLIC.Formatter.Emph); end CLIC_Ex.Commands; diff --git a/src/clic-config.ads b/src/clic-config.ads index 0da736c..7705a61 100644 --- a/src/clic-config.ads +++ b/src/clic-config.ads @@ -29,7 +29,7 @@ package CLIC.Config with Preelaborate is access function (Key : Config_Key; Value : TOML.TOML_Value) return Boolean; -- Return False when a Key/Value combination is not valid. Can be used to - -- check formating of string value like email address for instance. + -- check formatting of string value like email address for instance. procedure Import (This : in out Instance; Table : TOML.TOML_Value; diff --git a/src/clic-formatter.adb b/src/clic-formatter.adb new file mode 100644 index 0000000..f51c5fb --- /dev/null +++ b/src/clic-formatter.adb @@ -0,0 +1,49 @@ +with CLIC.TTY; +with CLIC.Markdown; + +package body CLIC.Formatter is + + Markdown_Enabled : Boolean := False; + + procedure Enable_Markdown is + begin + Markdown_Enabled := True; + end Enable_Markdown; + + procedure Force_Disable_TTY renames TTY.Force_Disable_TTY; + procedure Enable_Color (Force : Boolean := False) + renames TTY.Enable_Color; + + function Chapter (Str : String) return String is + (if Markdown_Enabled + then Markdown.Chapter (Str) + else TTY.Bold (Str)); + + function Description (Str : String) return String is + (if Markdown_Enabled + then Markdown.Code (Str) + else TTY.Description (Str)); + + function Version (Str : String) return String is + (if Markdown_Enabled + then Markdown.Italic (Str) + else TTY.Version (Str)); + + function Underline (Str : String) return String is + (if Markdown_Enabled + then Str + else TTY.Underline (Str)); + + -- Emph is used to highlight switches, so we use Code for the markdown + -- version. + function Emph (Str : String) return String is + (if Markdown_Enabled + then Markdown.Code (Str) + else TTY.Emph (Str)); + + function Terminal (Str : String) return String is + (if Markdown_Enabled + then Markdown.Code (Str) + else TTY.Terminal (Str)); + +end CLIC.Formatter; diff --git a/src/clic-formatter.ads b/src/clic-formatter.ads new file mode 100644 index 0000000..ff0c5b8 --- /dev/null +++ b/src/clic-formatter.ads @@ -0,0 +1,23 @@ +package CLIC.Formatter +with Preelaborate +is + + -- Provides markdown or TTY formatting for displaying help pages. + + procedure Force_Disable_TTY; + + procedure Enable_Markdown; + -- Enables markdown output of formatting functions. + + procedure Enable_Color (Force : Boolean := False); + -- Prepares colors for the terminal output. Unless Force, will do nothing + -- if a console redirection is detected. + + function Chapter (Str : String) return String; + function Description (Str : String) return String; + function Version (Str : String) return String; + function Underline (Str : String) return String; + function Emph (Str : String) return String; + function Terminal (Str : String) return String; + +end CLIC.Formatter; diff --git a/src/clic-markdown.adb b/src/clic-markdown.adb new file mode 100644 index 0000000..22a4fd0 --- /dev/null +++ b/src/clic-markdown.adb @@ -0,0 +1,20 @@ +with AAA.Strings; + +package body CLIC.Markdown is + + function Chapter (Str : String) return String is + ("### " & Str); + + function Plain_Text (Str : String) return String is + (Str); + + function Code (Str : String) return String is + ('`' & Str & '`'); + + function Bold (Str : String) return String is + ('*' & Str & '*'); + + function Italic (Str : String) return String is + ('_' & Str & '_'); + +end CLIC.Markdown; diff --git a/src/clic-markdown.ads b/src/clic-markdown.ads new file mode 100644 index 0000000..8d79e22 --- /dev/null +++ b/src/clic-markdown.ads @@ -0,0 +1,12 @@ + +package CLIC.Markdown +with Preelaborate +is + + function Chapter (Str : String) return String; + function Plain_Text (Str : String) return String; + function Code (Str : String) return String; + function Bold (Str : String) return String; + function Italic (Str : String) return String; + +end CLIC.Markdown; diff --git a/src/clic-subcommand-instance.adb b/src/clic-subcommand-instance.adb index 5b0bcd7..52457c4 100644 --- a/src/clic-subcommand-instance.adb +++ b/src/clic-subcommand-instance.adb @@ -389,6 +389,7 @@ package body CLIC.Subcommand.Instance is return; end if; + Put_Line (""); Put_Line (TTY_Chapter ("ALIASES")); for Elt in Registered_Aliases.Iterate loop @@ -396,7 +397,7 @@ package body CLIC.Subcommand.Instance is Table.Append (Tab); Table.Append (TTY_Description (To_String (Key (Elt)))); Table.Append (Tab); - Table.Append (Element (Elt).Flatten); + Table.Append (TTY_Terminal (Element (Elt).Flatten)); end loop; Table.Print (Separator => " ", Put_Line => Put_Line_For_Access'Access); @@ -418,11 +419,11 @@ package body CLIC.Subcommand.Instance is Put_Line (TTY_Chapter ("USAGE")); Put (" "); Put_Line - (TTY_Underline (Main_Command_Name) & + (TTY_Terminal (TTY_Underline (Main_Command_Name) & " " & TTY_Underline (Cmd.Name) & " [options] " & - Cmd.Usage_Custom_Parameters); + Cmd.Usage_Custom_Parameters)); -- We use the following two canaries to detect if a command is adding -- its own switches, in which case we need to show their specific help. @@ -472,13 +473,13 @@ package body CLIC.Subcommand.Instance is end if; Put_Line (TTY_Chapter ("USAGE")); - Put_Line (" " & TTY_Underline (Main_Command_Name) & + Put_Line (" " & TTY_Terminal (TTY_Underline (Main_Command_Name) & " [global options] " & - " [command options] []"); + " [command options] []")); Put_Line (""); - Put_Line (" " & TTY_Underline (Main_Command_Name) & " " & + Put_Line (" " & TTY_Terminal (TTY_Underline (Main_Command_Name) & " " & TTY_Underline ("help") & - " [|]"); + " [|]")); Put_Line (""); Put_Line (TTY_Chapter ("ARGUMENTS")); @@ -496,7 +497,7 @@ package body CLIC.Subcommand.Instance is Table.Append (TTY_Description ("")); Table.Append ("List of arguments for the command"); - Table.Print (Separator => " ", + Table.Print (Separator => " ", Put_Line => Put_Line_For_Access'Access); end; @@ -877,14 +878,16 @@ package body CLIC.Subcommand.Instance is if Has_Short and Has_Long then Table.Append (TTY_Description (Without_Arg (Short_Switch)) & - " (" & With_Arg (Long_Switch, Arg) & ")"); + " (" & TTY_Description (With_Arg (Long_Switch, Arg)) & ")"); elsif not Has_Short and Has_Long then Table.Append (TTY_Description (With_Arg (Long_Switch, Arg))); elsif Has_Short and not Has_Long then Table.Append (TTY_Description (With_Arg (Short_Switch, Arg))); end if; - Table.Append (Help); + -- Adding two spaces at the end will ensure a new line when printing in + -- markdown format. + Table.Append (Help & " "); Has_Printable_Rows := True; end Print_Row; @@ -956,6 +959,46 @@ package body CLIC.Subcommand.Instance is end if; end Display_Help; + ---------------------- + -- Iterate_Commands -- + ---------------------- + + procedure Iterate_Commands + (Process : not null access procedure (Group : Ada.Strings.Unbounded.Unbounded_String; + Cmd : not null Command_Access)) is + use Command_Maps; + use Group_Maps; + begin + + for Iter in Registered_Groups.Iterate loop + + declare + Group : constant Unbounded_String := Key (Iter); + begin + + for Name of Element (Iter) loop + Process (Group, Registered_Commands (To_Unbounded_String (Name))); + end loop; + end; + end loop; + + end Iterate_Commands; + + -------------------- + -- Iterate_Topics -- + -------------------- + + procedure Iterate_Topics + (Process : not null access procedure (Cmd : not null Help_Topic_Access)) is + begin + + for Topic of Registered_Topics loop + Process (Topic); + end loop; + + end Iterate_Topics; + + ------------- -- Execute -- ------------- @@ -973,8 +1016,8 @@ package body CLIC.Subcommand.Instance is end if; Put_Line (TTY_Chapter ("USAGE")); - Put_Line (" " & TTY_Underline (Main_Command_Name) & " " & - TTY_Underline ("help") & " [|]"); + Put_Line (" " & TTY_Terminal (TTY_Underline (Main_Command_Name) & " " & + TTY_Underline ("help") & " [|]")); Put_Line (""); Put_Line (TTY_Chapter ("ARGUMENTS")); diff --git a/src/clic-subcommand-instance.ads b/src/clic-subcommand-instance.ads index 1c559d9..79dc242 100644 --- a/src/clic-subcommand-instance.ads +++ b/src/clic-subcommand-instance.ads @@ -1,5 +1,7 @@ -- Instantiate this package to create a sub-command parser/executor +with Ada.Strings.Unbounded; + with CLIC.Config; generic @@ -20,13 +22,16 @@ generic -- Used to signal that the program should terminate with the give error -- code. Typicaly use GNAT.OS_Lib.OS_Exit. - -- The procedures below are used to format the output such as usage and - -- help. Use CLIC.Subcommand.No_TTY if you don't want or need formating. + -- The functions below are used to format the output such as usage and + -- help. Use CLIC.Subcommand.No_TTY if you don't want or need formatting. + -- CLIC also provides ready implementations in CLIC.Formatter, CLIC.TTY + -- and CLIC.Markdown. with function TTY_Chapter (Str : String) return String; with function TTY_Description (Str : String) return String; with function TTY_Version (Str : String) return String; with function TTY_Underline (Str : String) return String; with function TTY_Emph (Str : String) return String; + with function TTY_Terminal (Str : String) return String; Global_Options_In_subcommand_help : Boolean := True; -- When listing help for a subcommand, also include a section on global @@ -89,6 +94,16 @@ package CLIC.Subcommand.Instance is procedure Display_Help (Keyword : String); + procedure Iterate_Commands + (Process : not null access procedure (Group : Ada.Strings.Unbounded.Unbounded_String; + Cmd : not null Command_Access)); + -- Iterate over all registered commands sorted by group applying Process + + procedure Iterate_Topics + (Process : not null access procedure (Cmd : not null Help_Topic_Access)); + -- Iterate all registered topics applying Process + + Error_No_Command : exception; Command_Already_Defined : exception; @@ -121,9 +136,9 @@ private is (AAA.Strings.Empty_Vector .Append ("Shows information about commands and topics.") .Append ("See available commands with '" & - Main_Command_Name & " help commands'") + TTY_Terminal (Main_Command_Name & " help commands") & "'") .Append ("See available topics with '" & - Main_Command_Name & " help topics'.")); + TTY_Terminal (Main_Command_Name & " help topics") & "'.")); overriding procedure Setup_Switches diff --git a/src/clic-subcommand.ads b/src/clic-subcommand.ads index 105db56..656ac91 100644 --- a/src/clic-subcommand.ads +++ b/src/clic-subcommand.ads @@ -138,7 +138,7 @@ package CLIC.Subcommand is ----------------- type Help_Topic is limited interface; - -- This type encapsulate the content of an "help topic", i.e. a piece of + -- This type encapsulates the content of an "help topic", i.e. a piece of -- documentation that can displayed from the command line. type Help_Topic_Access is access all Help_Topic'Class; @@ -165,7 +165,7 @@ package CLIC.Subcommand is function No_TTY (Str : String) return String is (Str); -- Use this function for the TTY_* generic parameters of - -- CLIC.Subcommand.Instance if you don't want or need TTY formating. + -- CLIC.Subcommand.Instance if you don't want or need TTY formatting. private diff --git a/src/clic-tty.ads b/src/clic-tty.ads index d577a8b..5940920 100644 --- a/src/clic-tty.ads +++ b/src/clic-tty.ads @@ -19,7 +19,7 @@ is procedure Force_Disable_TTY with Post => not Is_TTY; - -- Disable TTY support even if availabe + -- Disable TTY support even if available -------------------- -- Color enabling --