Here's a patch to make menus optional in Texinfo source files. I based this on the code for the existing option "-c TREE_TRANSFORMATIONS=complete_tree_nodes_menus".
makeinfo will now add a menu to nodes that don't have one already and output it for Info output. This simplifies the creation of Texinfo source files, especially those created for HTML or PDF output where the contents of @menu blocks are not propagated. It would save updating menus manually, or else using specialized Emacs modes to edit Texinfo files. It would allow someone to miss out menus in the source file, if they didn't want to give menu entry descriptions. Adding a new section can give lots of errors if the menu of the parent node isn't updated. For example, if "Chapter Three" is missing in: @menu * Chapter One:: * Chapter Two:: * Chapter Four:: @end menu the error messages look like: tp/structure.texi:17: warning: node next `Chapter Two' in menu `Chapter Four' and in sectioning `Chapter Three' differ tp/structure.texi:20: warning: unreferenced node `Chapter Three' tp/structure.texi:20: warning: node `Chapter Four' is next for `Chapter Three' in sectioning but not in menu tp/structure.texi:20: warning: node `Chapter Two' is prev for `Chapter Three' in sectioning but not in menu tp/structure.texi:20: warning: node `Top' is up for `Chapter Three' in sectioning but not in menu tp/structure.texi:3: node `Top' lacks menu item for `Chapter Three' despite being its Up target tp/structure.texi:23: warning: node prev `Chapter Four' in menu `Chapter Two' and in sectioning `Chapter Three' differ which can be hard to make sense of. Allowing menus to be missed out would make it easier to fix these error messages. I suggest we change the manual to explain why someone might want to explicitly give a menu, for example if they want topic names to be different to node names or give more explanation of what a node is about other than its name. I haven't suggested just turning on 'complete_tree_nodes_menus' by default because that would be less strict and allow incomplete menus, which are probably not what the author of the document wants in their source file.
Index: NEWS =================================================================== --- NEWS (revision 6381) +++ NEWS (working copy) @@ -22,6 +22,10 @@ one of the relevant sections: http://www.gnu.org/software/texinfo/manual/texinfo/html_node/Document-Permissions.html ------------------------------------------------------------------------------- +* Language: + . @menu is now optional in nodes. For Info output, makeinfo will + automatically create a menu for nodes lacking one given explicitly. + 6.0 (26 June 2015) * Language: Index: tp/texi2any.pl =================================================================== --- tp/texi2any.pl (revision 6381) +++ tp/texi2any.pl (working copy) @@ -1302,7 +1302,10 @@ while(@input_files) { if ($tree_transformations{'complete_tree_nodes_menus'}) { Texinfo::Structuring::complete_tree_nodes_menus($parser, $tree); + } else { + Texinfo::Structuring::add_missing_menus($parser, $tree); } + if ($tree_transformations{'indent_menu_descriptions'}) { Texinfo::Convert::Plaintext::indent_menu_descriptions(undef, $parser); } Index: tp/Texinfo/Structuring.pm =================================================================== --- tp/Texinfo/Structuring.pm (revision 6381) +++ tp/Texinfo/Structuring.pm (working copy) @@ -43,6 +43,7 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPO # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. %EXPORT_TAGS = ( 'all' => [ qw( + add_missing_menus associate_internal_references complete_tree_nodes_menus elements_directions @@ -1683,6 +1684,40 @@ sub _new_block_command($$$) return $new_block; } +sub add_node_menu_if_missing($$) +{ + my $self = shift; + my $node = shift; + + if (!$node->{'extra'}->{'associated_section'}->{'section_childs'} + or $node->{'menus'} and @{$node->{'menus'}}) { + return; + } + + my @node_childs; + foreach my $child (@{$node->{'extra'}->{'associated_section'}->{'section_childs'}}) { + if ($child->{'extra'} and $child->{'extra'}->{'associated_node'}) { + push @node_childs, $child->{'extra'}->{'associated_node'}; + } + } + + my @pending; + for my $child (@node_childs) { + my $entry = _new_node_menu_entry($self, + $child->{'extra'}->{'node_content'}); + push @pending, $entry; + } + + # Add a menu to this node + my $section = $node->{'extra'}->{'associated_section'}; + my $current_menu = _new_block_command (\@pending, $section, 'menu'); + push @{$section->{'contents'}}, $current_menu; + push @{$section->{'contents'}}, {'type' => 'empty_line', + 'text' => "\n", + 'parent' => $section}; + push @{$node->{'menus'}}, $current_menu; +} + sub complete_node_menu($$) { my $self = shift; @@ -1784,6 +1819,25 @@ sub complete_node_menu($$) } # This should be called after sectioning_structure +sub add_missing_menus($$) +{ + my $self = shift; + my $root = shift; + if (!$root->{'type'} or $root->{'type'} ne 'document_root' + or !$root->{'contents'}) { + return undef; + } + foreach my $content (@{$root->{'contents'}}) { + if ($content->{'cmdname'} and $content->{'cmdname'} eq 'node' + and (scalar(@{$content->{'extra'}->{'nodes_manuals'}}) == 1) + and $content->{'extra'} + and $content->{'extra'}->{'associated_section'}) { + add_node_menu_if_missing($self, $content); + } + } +} + +# This should be called after sectioning_structure sub complete_tree_nodes_menus($$) { my $self = shift;
