@@ -389,7 +389,7 @@ impl HelpTemplate<'_, '_> {
389389 . collect :: < Vec < _ > > ( ) ;
390390 let subcmds = self . cmd . has_visible_subcommands ( ) ;
391391
392- let custom_headings = self
392+ let custom_arg_headings = self
393393 . cmd
394394 . get_arguments ( )
395395 . filter_map ( |arg| arg. get_help_heading ( ) )
@@ -434,8 +434,8 @@ impl HelpTemplate<'_, '_> {
434434 let _ = write ! ( self . writer, "{header}{help_heading}:{header:#}\n " , ) ;
435435 self . write_args ( & non_pos, "Options" , option_sort_key) ;
436436 }
437- if !custom_headings . is_empty ( ) {
438- for heading in custom_headings {
437+ if !custom_arg_headings . is_empty ( ) {
438+ for heading in custom_arg_headings {
439439 let args = self
440440 . cmd
441441 . get_arguments ( )
@@ -891,50 +891,49 @@ impl HelpTemplate<'_, '_> {
891891 ) ;
892892 }
893893
894- let custom_headings = self
895- . cmd
896- . get_subcommands ( )
897- . filter_map ( |cmd| cmd. get_help_heading ( ) )
898- . collect :: < FlatSet < _ > > ( ) ;
894+ let custom_sc_headings = self . cmd . get_subcommand_custom_help_headings ( ) ;
899895
900- // Write commands that have no custom heading
901- for ( _, subcommand) in ord_v
902- . iter ( )
903- . filter ( |item| item. 1 . get_help_heading ( ) . is_none ( ) )
904- . filter ( |item| item. 1 . get_name ( ) != "help" )
905- {
906- self . write_flat_subcommand ( subcommand, first) ;
907- }
896+ // Commands under default heading
897+ self . write_flat_subcommands_under_heading ( & ord_v, None , first, false ) ;
908898
909899 // Commands under custom headings
910- if !custom_headings. is_empty ( ) {
911- for heading in custom_headings {
912- let cmds = self
913- . cmd
914- . get_subcommands ( )
915- . filter ( |sc| {
916- if let Some ( help_heading) = sc. get_help_heading ( ) {
917- return help_heading == heading;
918- }
919- false
920- } )
921- . filter ( |sc| should_show_subcommand ( sc) )
922- . collect :: < Vec < _ > > ( ) ;
923-
924- if !cmds. is_empty ( ) {
925- for ( _, subcommand) in ord_v
926- . clone ( )
927- . into_iter ( )
928- . filter ( |item| item. 1 . get_help_heading ( ) == Some ( heading) )
929- {
930- self . write_flat_subcommand ( subcommand, first) ;
931- }
932- }
933- }
900+ for heading in custom_sc_headings {
901+ self . write_flat_subcommands_under_heading ( & ord_v, Some ( heading) , first, false ) ;
934902 }
935903
936904 // Help command
937- for ( _, subcommand) in ord_v. iter ( ) . filter ( |item| item. 1 . get_name ( ) == "help" ) {
905+ self . write_flat_subcommands_under_heading ( & ord_v, None , first, true ) ;
906+ }
907+
908+ fn write_flat_subcommands_under_heading (
909+ & mut self ,
910+ ord_v : & BTreeMap < ( usize , & str ) , & Command > ,
911+ heading : Option < & str > ,
912+ first : & mut bool ,
913+ include_help : bool ,
914+ ) {
915+ debug ! ( "help_template::write subcommand under heading: `{heading:?}`" ) ;
916+ // If a custom heading is set ignore the include help flag
917+ let bt: Vec < ( & ( usize , & str ) , & & Command ) > = if heading. is_some ( ) {
918+ ord_v
919+ . iter ( )
920+ . filter ( |item| item. 1 . get_help_heading ( ) == heading)
921+ . collect ( )
922+ } else {
923+ ord_v
924+ . iter ( )
925+ . filter ( |item| item. 1 . get_help_heading ( ) == heading)
926+ . filter ( |item| {
927+ if include_help {
928+ item. 1 . get_name ( ) == "help"
929+ } else {
930+ item. 1 . get_name ( ) != "help"
931+ }
932+ } )
933+ . collect ( )
934+ } ;
935+
936+ for ( _, subcommand) in bt {
938937 self . write_flat_subcommand ( subcommand, first) ;
939938 }
940939 }
@@ -988,7 +987,6 @@ impl HelpTemplate<'_, '_> {
988987 debug ! ( "HelpTemplate::write_subcommands" ) ;
989988 use std:: fmt:: Write as _;
990989 let literal = & self . styles . get_literal ( ) ;
991- let header = & self . styles . get_header ( ) ;
992990
993991 // The shortest an arg can legally be is 2 (i.e. '-x')
994992 let mut longest = 2 ;
@@ -1006,9 +1004,6 @@ impl HelpTemplate<'_, '_> {
10061004 if let Some ( long) = subcommand. get_long_flag ( ) {
10071005 let _ = write ! ( styled, ", {literal}--{long}{literal:#}" , ) ;
10081006 }
1009- // if subcommand.get_help_heading().is_some() {
1010- // has_heading = true;
1011- // }
10121007 longest = longest. max ( styled. display_width ( ) ) ;
10131008 ord_v. insert ( ( subcommand. get_display_order ( ) , styled) , subcommand) ;
10141009 }
@@ -1017,63 +1012,44 @@ impl HelpTemplate<'_, '_> {
10171012
10181013 let next_line_help = self . will_subcommands_wrap ( cmd. get_subcommands ( ) , longest) ;
10191014
1020- let custom_headings = self
1021- . cmd
1022- . get_subcommands ( )
1023- . filter_map ( |cmd| cmd. get_help_heading ( ) )
1024- . collect :: < FlatSet < _ > > ( ) ;
1015+ let custom_sc_headings = self . cmd . get_subcommand_custom_help_headings ( ) ;
1016+
1017+ // User commands without heading
1018+ self . write_subcommands_under_heading ( & ord_v, None , next_line_help, longest) ;
1019+
1020+ // User commands with heading
1021+ for heading in custom_sc_headings {
1022+ self . write_subcommands_under_heading ( & ord_v, Some ( heading) , next_line_help, longest) ;
1023+ }
1024+ }
1025+
1026+ fn write_subcommands_under_heading (
1027+ & mut self ,
1028+ ord_v : & BTreeMap < ( usize , StyledStr ) , & Command > ,
1029+ heading : Option < & str > ,
1030+ next_line_help : bool ,
1031+ longest : usize ,
1032+ ) {
1033+ debug ! ( "help_template::write subcommand under heading: `{heading:?}`" ) ;
1034+ use std:: fmt:: Write as _;
1035+ let header = & self . styles . get_header ( ) ;
1036+
1037+ if let Some ( heading) = heading {
1038+ self . writer . push_str ( "\n \n " ) ;
1039+ let _ = write ! ( self . writer, "{header}{heading}:{header:#}\n " , ) ;
1040+ }
10251041
1026- // First for the commands that don't have a heading
10271042 for ( i, ( sc_str, sc) ) in ord_v
10281043 . clone ( )
10291044 . into_iter ( )
1030- . filter ( |item| item. 1 . get_help_heading ( ) . is_none ( ) )
1045+ . filter ( |item| item. 1 . get_help_heading ( ) == heading )
10311046 . enumerate ( )
10321047 {
1033- debug ! ( "Processing without heading {}" , sc. get_name( ) ) ;
10341048 if 0 < i {
10351049 self . writer . push_str ( "\n " ) ;
10361050 }
10371051 self . write_subcommand ( sc_str. 1 , sc, next_line_help, longest) ;
10381052 }
1039-
1040- // Commands under custom headings
1041- if !custom_headings. is_empty ( ) {
1042- for heading in custom_headings {
1043- let cmds = self
1044- . cmd
1045- . get_subcommands ( )
1046- . filter ( |sc| {
1047- if let Some ( help_heading) = sc. get_help_heading ( ) {
1048- return help_heading == heading;
1049- }
1050- false
1051- } )
1052- . filter ( |sc| should_show_subcommand ( sc) )
1053- . collect :: < Vec < _ > > ( ) ;
1054-
1055- if !cmds. is_empty ( ) {
1056- self . writer . push_str ( "\n \n " ) ;
1057- let _ = write ! ( self . writer, "{header}{heading}:{header:#}\n " , ) ;
1058- for ( i, ( sc_str, sc) ) in ord_v
1059- . clone ( )
1060- . into_iter ( )
1061- . filter ( |item| item. 1 . get_help_heading ( ) == Some ( heading) )
1062- . enumerate ( )
1063- {
1064- debug ! (
1065- "Processing with heading: name {}, heading {}" ,
1066- sc. get_name( ) ,
1067- heading
1068- ) ;
1069- if 0 < i {
1070- self . writer . push_str ( "\n " ) ;
1071- }
1072- self . write_subcommand ( sc_str. 1 , sc, next_line_help, longest) ;
1073- }
1074- }
1075- }
1076- }
10771053 }
10781054
10791055 /// Will use next line help on writing subcommands.
0 commit comments