From 784b8e61c7c9e73b0dba471719101554bc77ec88 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 22 Aug 2018 02:54:11 -0700 Subject: [PATCH] Add @GroupTitle and @GroupInitialArguments commands Previously, there was no way to modify the subsection heading of a Group, but the documentation even stated "Note that it is currently not possible to give a header to the Group in the manual..." Hence, the addition of a @GroupTitle command to allow exactly that. In addition, the functions in a Group often share an initial set of arguments, and so this adds a @GroupInitialArguments command to allow such arguments to be defined once for the declarations in a @BeginGroup/@EndGroup block. Both commands are added to the documentation, with examples in the Grouping section. --- doc/Comments.xml | 40 ++++++++++++++++++++++++++--- gap/DocumentationTree.gi | 7 +++++- gap/Parser.gi | 54 +++++++++++++++++++++++++++++++++++++--- gap/ToolFunctions.gi | 12 +++++++-- 4 files changed, 102 insertions(+), 11 deletions(-) diff --git a/doc/Comments.xml b/doc/Comments.xml index 5d738e54..79f48656 100644 --- a/doc/Comments.xml +++ b/doc/Comments.xml @@ -302,6 +302,25 @@ DeclareOperation( "GroupedOperation", ]]> + +@GroupTitle +@GroupTitle title +Sets the subsection heading for the current group to title. In the +absence of any @GroupTitle command, the heading will be the name of the +first entry in the group. See for more information. + + + +@GroupInitialArguments +@GroupInitialArguments args +Sets the common initial arguments for the entries in the current group to be +args. The argument list for any function subsequently added to the +group without any args specified will be args, and args will be +prepended to any arguments specified for a particular function. The setting is +cleared by an @EndGroup command. See for more +information. + + @Level @Level lvl @@ -556,8 +575,9 @@ a function, operation, etc., it is possible to group them into suitable chunks. This can be particularly useful if there are several definitions of an operation with several different argument types, all doing more or less the same to the arguments. Then their manual items can be grouped, sharing the same description and return type information. -Note that it is currently not possible to give a header to the Group in the manual, -but the generated ManItem heading of the first entry will be used. +You can give a heading to the Group in the manual with the @GroupTitle +command; if that is not supplied, then the generated ManItem heading of the +first entry will be used as the heading.

Note that group names are globally unique throughout the whole manual. @@ -570,9 +590,19 @@ same group name, in different places, and these all will refer to the same group Moreover, this means that you can add items to a group via the @Group command in the &AutoDoc; comment of an arbitrary declaration, at any time. +

+Since often the functions in a Group share common initial arguments, you can +set a list of common arguments to be prepended to all declarations within a +given @BeginGroup/@EndGroup pair with the @GroupInitialArguments +command. + +

+ The following code

- - + A family of operations + + diff --git a/gap/DocumentationTree.gi b/gap/DocumentationTree.gi index 30ed3337..69febebc 100644 --- a/gap/DocumentationTree.gi +++ b/gap/DocumentationTree.gi @@ -623,10 +623,15 @@ end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForGroupRep, IsStream ], function( node, filestream ) + local head; if node!.level > ValueOption( "level_value" ) then return; fi; - AutoDoc_WriteDocEntry( filestream, node!.content ); + head := fail; + if IsBound( node!.title_string ) then + head := node!.title_string; + fi; + AutoDoc_WriteDocEntry( filestream, node!.content, head ); end ); ## diff --git a/gap/Parser.gi b/gap/Parser.gi index 5ea1fc50..b8306427 100644 --- a/gap/Parser.gi +++ b/gap/Parser.gi @@ -77,7 +77,11 @@ InstallGlobalFunction( AutoDoc_Type_Of_Item, entries := [ "Func", "global_functions" ]; has_filters := "No"; if not IsBound( item_rec!.arguments ) then - item_rec!.arguments := "arg"; + if IsBound( item_rec!.initial_args ) then + item_rec!.arguments := item_rec!.initial_args; + else + item_rec!.arguments := "arg"; + fi; fi; elif PositionSublist( type, "DeclareGlobalVariable" ) <> fail then entries := [ "Var", "global_variables" ]; @@ -116,7 +120,7 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, function( filename_list, tree, default_chapter_data ) local current_item, flush_and_recover, chapter_info, current_string_list, Scan_for_Declaration_part, flush_and_prepare_for_item, current_line, filestream, - level_scope, scope_group, read_example, command_function_record, autodoc_read_line, + level_scope, scope_group, scope_initial_args, read_example, command_function_record, autodoc_read_line, current_command, was_declaration, filename, system_scope, groupnumber, chunk_list, rest_of_file_skipped, context_stack, new_man_item, add_man_item, Reset, read_code, title_item, title_item_list, plain_text_mode, current_line_unedited, @@ -159,6 +163,9 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, if IsBound( scope_group ) then SetGroupName( man_item, scope_group ); fi; + if IsBound( scope_initial_args ) then + man_item!.initial_args := scope_initial_args; + fi; man_item!.chapter_info := ShallowCopy( chapter_info ); man_item!.tester_names := fail; return man_item; @@ -267,7 +274,10 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, ##Adjust arguments if not IsBound( current_item!.arguments ) then if IsInt( has_filters ) then - if has_filters = 1 then + if IsBound( current_item!.initial_args ) then + current_item!.arguments := + current_item!.initial_args; + elif has_filters = 1 then current_item!.arguments := "arg"; else current_item!.arguments := JoinStringsWithSeparator( List( [ 1 .. has_filters ], i -> Concatenation( "arg", String( i ) ) ), "," ); @@ -561,8 +571,14 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, fi; scope_group := ReplacedString( current_command[ 2 ], " ", "_" ); end, + @GroupInitialArguments := function() + scope_initial_args := current_command[ 2 ]; + current_item := new_man_item(); + current_item!.initial_args := current_command[ 2 ]; + end, @EndGroup := function() Unbind( scope_group ); + Unbind( scope_initial_args ); end, @Description := function() current_item := new_man_item(); @@ -580,8 +596,16 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, fi; end, @Arguments := function() + local composed_arguments; + if IsBound( scope_initial_args ) and + Length( scope_initial_args ) > 0 then + composed_arguments := + Concatenation( scope_initial_args, ", ", current_command[ 2 ] ); + else + composed_arguments := current_command[ 2 ]; + fi; current_item := new_man_item(); - current_item!.arguments := current_command[ 2 ]; + current_item!.arguments := composed_arguments; end, @Label := function() current_item := new_man_item(); @@ -593,6 +617,28 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, group_name := ReplacedString( current_command[ 2 ], " ", "_" ); SetGroupName( current_item, group_name ); end, + @GroupTitle := function() + local group_name, chap_info, group_obj; + current_item := new_man_item(); + if not HasGroupName( current_item ) then + ErrorWithPos( "found @GroupTitle with no Group set" ); + fi; + group_name := GroupName( current_item ); + chap_info := fail; + if HasChapterInfo( current_item ) then + chap_info := ChapterInfo( current_item ); + elif IsBound( current_item!.chapter_info ) then + chap_info := current_item!.chapter_info; + fi; + if (chap_info = fail or chap_info = [ ]) then + chap_info := chapter_info; + fi; + if Length( chap_info ) <> 2 then + ErrorWithPos( "can only set @GroupTitle within a Chapter and Section."); + fi; + group_obj := DocumentationGroup( tree, group_name, chap_info ); + group_obj!.title_string := current_command[ 2 ]; + end, @ChapterInfo := function() local current_chapter_info; current_item := new_man_item(); diff --git a/gap/ToolFunctions.gi b/gap/ToolFunctions.gi index 5f35582f..0f9055f6 100644 --- a/gap/ToolFunctions.gi +++ b/gap/ToolFunctions.gi @@ -25,7 +25,7 @@ end ); ## InstallGlobalFunction( AutoDoc_WriteDocEntry, - function( filestream, list_of_records ) + function( filestream, list_of_records, maybe_heading... ) local return_value, description, current_description, labels, i; # look for a good return value (it should be the same everywhere) @@ -78,7 +78,15 @@ InstallGlobalFunction( AutoDoc_WriteDocEntry, od; AppendTo( filestream, ">\n" ); - # Function heades + # Next possibly the heading for the entry + if Length( maybe_heading ) > 0 then + maybe_heading := maybe_heading[ 1 ]; + if IsString( maybe_heading ) then + AppendTo( filestream, "", maybe_heading, "\n" ); + fi; + fi; + + # Function headers for i in list_of_records do AppendTo( filestream, " <", i!.item_type, " " ); if i!.arguments <> fail and i!.item_type <> "Var" then