diff --git a/CHANGES.md b/CHANGES.md index 1511fd05..b3a45bae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ This file describes changes in the AutoDoc package. environment variable and `relativePath` global option - Add Markdown-style headings `#`/`##`/`###` as aliases for `@Chapter`/`@Section`/`@Subsection` in `.autodoc` files and doc comments + - Add `@Appendix` for generating appendix XML from `.autodoc` input - Add support for documenting `DeclareSynonym` and `DeclareSynonymAttr` declarations - Add `@ItemType` to override the type of a declaration, which is diff --git a/doc/Comments.autodoc b/doc/Comments.autodoc index 219426b4..baf67219 100644 --- a/doc/Comments.autodoc +++ b/doc/Comments.autodoc @@ -243,6 +243,23 @@ If you use all three commands, i.e., title is used for the headline, label for cross-referencing, and name for setting the same chapter as active chapter again. +@Subsection @Appendix name +@SubsectionLabel @Appendix + +@Index "@Appendix" `@Appendix` +This is analogous to @Chapter, but generates `Appendix` +elements instead of `Chapter` elements. When scaffolding generates the main +XML file, appendices created this way are included automatically after any +files listed in `scaffold.appendix`. + +Example: + +```@listing +@Appendix Supplementary material + +@Section Additional tables +``` + @Subsection @Section name @SubsectionLabel @Section diff --git a/gap/AutoDocMainFunction.gi b/gap/AutoDocMainFunction.gi index 80215fc5..f4deaeda 100644 --- a/gap/AutoDocMainFunction.gi +++ b/gap/AutoDocMainFunction.gi @@ -155,6 +155,10 @@ InstallGlobalFunction( CreateMainPage, AppendTo( filestream, "<#Include SYSTEM \"", i, "\">\n" ); od; fi; + if IsBound( opt.autodoc_appendix_file ) and + ( not IsBound( opt.appendix ) or not opt.autodoc_appendix_file in opt.appendix ) then + AppendTo( filestream, "<#Include SYSTEM \"", opt.autodoc_appendix_file, "\">\n" ); + fi; if IsBound( opt.bib ) and opt.bib <> false then AppendTo( filestream, "\n" ); diff --git a/gap/DocumentationTree.gd b/gap/DocumentationTree.gd index 0764222e..6ada159c 100644 --- a/gap/DocumentationTree.gd +++ b/gap/DocumentationTree.gd @@ -45,6 +45,7 @@ DeclareAttribute( "GroupName", IsTreeForDocumentationNode ); DeclareOperation( "DocumentationTree", [ ] ); DeclareOperation( "StructurePartInTree", [ IsTreeForDocumentation, IsList ] ); DeclareOperation( "ChapterInTree", [ IsTreeForDocumentation, IsString ] ); +DeclareOperation( "AppendixInTree", [ IsTreeForDocumentation, IsString ] ); DeclareOperation( "SectionInTree", [ IsTreeForDocumentation, IsString, IsString ] ); DeclareOperation( "SubsectionInTree", [ IsTreeForDocumentation, IsString, IsString, IsString ] ); DeclareOperation( "DocumentationExample", [ IsString ] ); diff --git a/gap/DocumentationTree.gi b/gap/DocumentationTree.gi index 1478121e..934606f0 100644 --- a/gap/DocumentationTree.gi +++ b/gap/DocumentationTree.gi @@ -377,12 +377,24 @@ end ); ## #################################### -## +## InstallMethod( ChapterInTree, [ IsTreeForDocumentation, IsString ], function( tree, name ) return StructurePartInTree( tree, [ name ] ); end ); +## +InstallMethod( AppendixInTree, [ IsTreeForDocumentation, IsString ], + function( tree, name ) + local node; + + node := ChapterInTree( tree, name ); + node!.is_appendix := true; + SetLabel( node, + Concatenation( "Appendix_", AUTODOC_NormalizeGeneratedLabel( name ) ) ); + return node; +end ); + ## InstallMethod( SectionInTree, [ IsTreeForDocumentation, IsString, IsString ], function( tree, chapter_name, section_name ) @@ -476,17 +488,32 @@ end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentation, IsDirectory ], function( tree, path_to_xmlfiles ) - local stream, i; + local stream, appendix_stream, i; stream := AUTODOC_OutputTextFile( path_to_xmlfiles, _AUTODOC_GLOBAL_OPTION_RECORD.AutoDocMainFile ); AppendTo( stream, AUTODOC_XML_HEADER ); + appendix_stream := fail; for i in tree!.content do - if not IsTreeForDocumentationNodeForChapterRep( i ) then + if IsTreeForDocumentationNodeForChapterRep( i ) then + if IsBound( i!.is_appendix ) and i!.is_appendix = true then + if appendix_stream = fail then + appendix_stream := AUTODOC_OutputTextFile( + path_to_xmlfiles, + "_AutoDocAppendicesMainFile.xml" + ); + AppendTo( appendix_stream, AUTODOC_XML_HEADER ); + fi; + WriteDocumentation( i, appendix_stream, path_to_xmlfiles ); + else + WriteDocumentation( i, stream, path_to_xmlfiles ); + fi; + else Error( "this should never happen" ); fi; - ## FIXME: If there is anything else than a chapter, this will break! - WriteDocumentation( i, stream, path_to_xmlfiles ); od; + if appendix_stream <> fail then + CloseStream( appendix_stream ); + fi; WriteChunks( tree, path_to_xmlfiles ); @@ -500,7 +527,7 @@ end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForChapterRep, IsStream, IsDirectory ], function( node, stream, path_to_xmlfiles ) - local filename, chapter_stream; + local filename, chapter_stream, element_name; if ForAll( node!.content, IsEmptyNode ) then return; @@ -510,7 +537,11 @@ InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForChapterRep, Is chapter_stream := AUTODOC_OutputTextFile( path_to_xmlfiles, filename ); AppendTo( stream, "<#Include SYSTEM \"", filename, "\">\n" ); AppendTo( chapter_stream, AUTODOC_XML_HEADER ); - AUTODOC_WriteStructuralNode( node, "Chapter", chapter_stream ); + element_name := "Chapter"; + if IsBound( node!.is_appendix ) and node!.is_appendix = true then + element_name := "Appendix"; + fi; + AUTODOC_WriteStructuralNode( node, element_name, chapter_stream ); CloseStream( chapter_stream ); end ); diff --git a/gap/Magic.gd b/gap/Magic.gd index e9c75a73..6af80b98 100644 --- a/gap/Magic.gd +++ b/gap/Magic.gd @@ -136,7 +136,9 @@ #! #! This entry is similar to opt.scaffold.includes but is used #! to specify files to include after the main body of the manual, -#! i.e. typically appendices. +#! i.e. typically appendices written directly in &GAPDoc; XML. +#! Appendices created with @Appendix are included automatically +#! after these files when scaffolding generates the main XML file. #! #! #! bib diff --git a/gap/Magic.gi b/gap/Magic.gi index 16846caf..bbc3bae0 100644 --- a/gap/Magic.gi +++ b/gap/Magic.gi @@ -510,6 +510,10 @@ function( arg ) CreateEntitiesPage( gapdoc.bookname, doc_dir, scaffold ); if IsBound( scaffold.MainPage ) and scaffold.MainPage <> false then + if ForAny( tree!.content, + node -> IsBound( node!.is_appendix ) and node!.is_appendix = true ) then + scaffold.autodoc_appendix_file := "_AutoDocAppendicesMainFile.xml"; + fi; CreateMainPage( gapdoc.bookname, doc_dir, scaffold ); fi; fi; diff --git a/gap/Parser.gi b/gap/Parser.gi index 7306e2f3..8af927f0 100644 --- a/gap/Parser.gi +++ b/gap/Parser.gi @@ -800,8 +800,18 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, local scope_chapter; scope_chapter := ReplacedString( current_command[ 2 ], " ", "_" ); SetCurrentItem( ChapterInTree( tree, scope_chapter ) ); + Unbind( chapter_info[ 2 ] ); + Unbind( chapter_info[ 3 ] ); chapter_info[ 1 ] := scope_chapter; end, + @Appendix := function() + local scope_appendix; + scope_appendix := ReplacedString( current_command[ 2 ], " ", "_" ); + SetCurrentItem( AppendixInTree( tree, scope_appendix ) ); + Unbind( chapter_info[ 2 ] ); + Unbind( chapter_info[ 3 ] ); + chapter_info[ 1 ] := scope_appendix; + end, @ChapterLabel := function() local scope_chapter, label_name; if not IsBound( chapter_info[ 1 ] ) then diff --git a/tst/AutoDocTest/doc/appendix.autodoc b/tst/AutoDocTest/doc/appendix.autodoc new file mode 100644 index 00000000..9083a735 --- /dev/null +++ b/tst/AutoDocTest/doc/appendix.autodoc @@ -0,0 +1,4 @@ +@Appendix Plain-text appendix + +This appendix is written in `.autodoc` format and is expected to be included +through scaffold.appendix. diff --git a/tst/AutoDocTest/doc/appendix1.xml b/tst/AutoDocTest/doc/appendix1.xml new file mode 100644 index 00000000..c74817b6 --- /dev/null +++ b/tst/AutoDocTest/doc/appendix1.xml @@ -0,0 +1,9 @@ + + + + XML fixture appendix +

+ This hand-written XML appendix exercises the existing + scaffold.appendix hook alongside generated @Appendix + content. + diff --git a/tst/AutoDocTest/gap/AutoDocTest.gd b/tst/AutoDocTest/gap/AutoDocTest.gd index d1ef500e..3cde42a0 100644 --- a/tst/AutoDocTest/gap/AutoDocTest.gd +++ b/tst/AutoDocTest/gap/AutoDocTest.gd @@ -25,3 +25,8 @@ DeclareAttribute( "AutoDocTest_Attribute", IsGroup ); #! #! `AutoDocTest_Property` is a tiny property used to exercise method docs. DeclareProperty( "AutoDocTest_Property", IsGroup ); + +#! +#! `AutoDocTest_Method` is declared separately so the fixture package loads +#! cleanly when building its manual. +DeclareOperation( "AutoDocTest_Method", [ IsGroup ] ); diff --git a/tst/AutoDocTest/makedoc.g b/tst/AutoDocTest/makedoc.g index 4033297a..ecbdf4ea 100644 --- a/tst/AutoDocTest/makedoc.g +++ b/tst/AutoDocTest/makedoc.g @@ -3,13 +3,14 @@ LoadPackage("AutoDocTest"); AutoDoc(rec( autodoc := rec( - files := [ "doc/chapter2.autodoc" ], + files := [ "doc/chapter2.autodoc", "doc/appendix.autodoc" ], ), gapdoc := rec( files := [ "gap/AutoDocTest.gd", "gap/AutoDocTest.gi" ], ), scaffold := rec( includes := [ "chapter1.xml" ], + appendix := [ "appendix1.xml" ], bib := "AutoDocTest.bib", ), )); diff --git a/tst/AutoDocTest/tst/manual.expected/_Appendix_Plain-text_appendix.xml b/tst/AutoDocTest/tst/manual.expected/_Appendix_Plain-text_appendix.xml new file mode 100644 index 00000000..da2a62dd --- /dev/null +++ b/tst/AutoDocTest/tst/manual.expected/_Appendix_Plain-text_appendix.xml @@ -0,0 +1,11 @@ + + + + +Plain-text appendix + +

+This appendix is written in .autodoc format and is expected to be included +through scaffold.appendix. + + diff --git a/tst/AutoDocTest/tst/manual.expected/_AutoDocAppendicesMainFile.xml b/tst/AutoDocTest/tst/manual.expected/_AutoDocAppendicesMainFile.xml new file mode 100644 index 00000000..c198a949 --- /dev/null +++ b/tst/AutoDocTest/tst/manual.expected/_AutoDocAppendicesMainFile.xml @@ -0,0 +1,4 @@ + + + +<#Include SYSTEM "_Appendix_Plain-text_appendix.xml"> diff --git a/tst/AutoDocTest/tst/manual.expected/_Chapter_SourceAPI.xml b/tst/AutoDocTest/tst/manual.expected/_Chapter_SourceAPI.xml index e310947c..c04aaaf6 100644 --- a/tst/AutoDocTest/tst/manual.expected/_Chapter_SourceAPI.xml +++ b/tst/AutoDocTest/tst/manual.expected/_Chapter_SourceAPI.xml @@ -46,6 +46,16 @@ +

+ AutoDocTest_Method is declared separately so the fixture package loads + cleanly when building its manual. + + + +

+ + +

diff --git a/tst/manual.expected/_Chapter_Comments.xml b/tst/manual.expected/_Chapter_Comments.xml index a6690c1f..7f86a5b9 100644 --- a/tst/manual.expected/_Chapter_Comments.xml +++ b/tst/manual.expected/_Chapter_Comments.xml @@ -274,6 +274,26 @@ for setting the same chapter as active chapter again.

+ +@Appendix name + +

+@Appendix +This is analogous to @Chapter, but generates Appendix +elements instead of Chapter elements. When scaffolding generates the main +XML file, appendices created this way are included automatically after any +files listed in scaffold.appendix. +

+Example: +

+

+

+ + @Section name diff --git a/tst/manual.expected/_Chapter_Reference.xml b/tst/manual.expected/_Chapter_Reference.xml index 5fa123b4..fbdca2d6 100644 --- a/tst/manual.expected/_Chapter_Reference.xml +++ b/tst/manual.expected/_Chapter_Reference.xml @@ -161,7 +161,9 @@ This entry is similar to opt.scaffold.includes but is used to specify files to include after the main body of the manual, - i.e. typically appendices. + i.e. typically appendices written directly in &GAPDoc; XML. + Appendices created with @Appendix are included automatically + after these files when scaffolding generates the main XML file. bib