Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
This file describes changes in the AutoDoc package.

## 2026.05.03
- Make `AutoDoc()` infer the package directory from `INPUT_FILENAME()`
when called from a `makedoc.g` file outside the package root
- Deprecate calling `AutoDoc()` with a package name
- Deprecate using GAP global options to pass settings to `AutoDoc()`,
suggest using option records instead

## 2026.03.18
- Fix running the test suite via `TestPackage("AutoDoc")` when the
current working directory is not the package root
Expand Down
13 changes: 7 additions & 6 deletions doc/Tutorials.autodoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ then adopt additional features when useful.

Suppose your package is already up and running, but so far has no
manual. Then you can rapidly generate a <Q>scaffold</Q> for a package manual
using the <Ref Func="AutoDoc"/> command like this,
while running &GAP; from within your package's directory (the
one containing the <F>PackageInfo.g</F> file):
using the <Ref Func="AutoDoc"/> command like this:
```@listing
LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true ) );
```
This first reads the <F>PackageInfo.g</F> file from the current
directory. It extracts information about the package from it
When called from a file such as <F>makedoc.g</F>, &AutoDoc; uses the
directory containing that file as the package directory. Otherwise, it
falls back to the current directory. In either case it then reads the
<F>PackageInfo.g</F> file from that package directory. It extracts information
about the package from it
(such as its name and version, see Section <Ref Sect="Subsection_Tut:Scaffolds:Title"/>).
It then creates two XML files <F>doc/_main.xml</F> and
<F>doc/title.xml</F> inside the package directory. Finally, it runs
Expand Down Expand Up @@ -84,7 +85,7 @@ AutoDoc( rec( autodoc := true ) );
QUIT;
```
Then you can regenerate the package manual from the command line with the
following command, executed from within the package directory:
following command:
```@listing
gap makedoc.g
```
Expand Down
28 changes: 15 additions & 13 deletions gap/Magic.gd
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,29 @@
#! The parameters have the following meanings:
#! <List>
#!
#! <Mark><A>packageOrDirectory</A></Mark>
#! <Mark><A>pkgdir</A></Mark>
#! <Item>
#! The purpose of this parameter is twofold: to determine the package
#! This optional parameter is used to determine the package
#! directory in which &AutoDoc; will operate, and to find the metadata
#! concerning the package being documented. The parameter is either a
#! string, an <C>IsDirectory</C> object, or omitted.
#! If it is a string, &AutoDoc; interprets it as the name of a
#! package, uses the metadata of the first package known to &GAP;
#! with that name, and uses the <C>InstallationPath</C> specified in that
#! metadata as the package directory. If <A>packageOrDirectory</A> is
#! an <C>IsDirectory</C> object, this is used as package directory;
#! if the argument is omitted, then the current directory is used.
#! In the last two cases, the specified directory must contain a
#! concerning the package being documented. If given, it should be
#! an <C>IsDirectory</C> object. If the argument is omitted, then &AutoDoc;
#! checks if it was called from a <F>makedoc.g</F> file or similar, and if so,
#! uses the directory this is contained in. Otherwise the current
#! directory is used. In both cases, the specified directory must contain a
#! <F>PackageInfo.g</F> file, and &AutoDoc; extracts all needed metadata
#! from that. The <C>IsDirectory</C> form is for example useful if you
#! have multiple versions of the package around and want to make sure the
#! documentation of the correct version is built.
#! <P/>
#! For backwards compatibility, it is also possible to pass a package name
#! as this argument, which then is resolved to the package directory of
#! the first instance of this package &GAP; knows about. However, this is
#! deprecated, as it is unreliable in the presence of multiple copies of a
#! package.
#! <P/>
#! Note that when using <C>AutoDocWorksheet</C> (see
#! <Ref Sect='Section_AutoDocWorksheet'/>), there is
#! no parameter corresponding to <A>packageOrDirectory</A> and so the
#! no parameter corresponding to <A>pkgdir</A> and so the
#! <Q>package directory</Q> is always the current directory, and
#! there is no metadata.
#! </Item>
Expand Down Expand Up @@ -461,7 +463,7 @@
#! <Ref Func="AutoDoc"/> call inside <F>makedoc.g</F>.
#!
#! @Returns nothing
#! @Arguments [packageOrDirectory], [optrec]
#! @Arguments [pkgdir], [optrec]
DeclareGlobalFunction( "AutoDoc" );

DeclareGlobalFunction( "AutoDoc_INTERN" );
Expand Down
32 changes: 27 additions & 5 deletions gap/Magic.gi
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#
InstallGlobalFunction( AutoDoc,
function( arg )
local pkgname, pkginfo, pkgdir, opt, file;
local pkgname, pkginfo, pkgdir, opt, file,
input_filename, path_positions;

if Length( arg ) >= 3 then
Error( "too many arguments" );
Expand All @@ -23,9 +24,24 @@ function( arg )

# check the first argument
if Length(arg) = 0 then
pkgdir := DirectoryCurrent( );
input_filename := INPUT_FILENAME();
if IsString( input_filename ) and
input_filename <> "*stdin*" and
IsReadableFile( input_filename ) then
path_positions := PositionsProperty( input_filename, x -> x = '/' );
if IsEmpty( path_positions ) then
pkgdir := DirectoryCurrent( );
else
pkgdir := Directory(
input_filename{ [ 1 .. Last( path_positions ) - 1 ] }
);
fi;
else
pkgdir := DirectoryCurrent( );
fi;
elif IsString( arg[1] ) then
pkgname := Remove( arg, 1 );
Print("#W AutoDoc: passing pkgname as first argument to AutoDoc is deprecated");
elif IsDirectory( arg[1] ) then
pkgdir := Remove( arg, 1 );
fi;
Expand Down Expand Up @@ -74,19 +90,25 @@ function( is_worksheet, pkgname, pkginfo, pkgdir, opt )
pkgdirstr, docdirstr,
title_page, tree,
position_document_class,
args;
args, used_legacy_value_options;

#
# Check for user supplied options. If present, they take
# precedence over any defaults as well as the opt record.
# Deprecated feature: Check for user supplied global options. If present,
# they take precedence over any defaults as well as the opt record.
#
used_legacy_value_options := false;
for key in [ "dir", "scaffold", "autodoc", "gapdoc", "extract_examples" ] do
val := ValueOption( key );
if val <> fail then
opt.(key) := val;
used_legacy_value_options := true;
fi;
od;

if used_legacy_value_options then
Print("#W passing options via GAP's global options system is deprecated; use an option record instead\n");
fi;

#
# Setup the output directory
#
Expand Down
6 changes: 6 additions & 0 deletions tst/autodoctest-manual.tst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ gap> AUTODOC_RunPackageScenario( pkgdir, olddir, rec(
> makedoc := "makedoc.g",
> doc_expected := "tst/manual.expected",
> ) );
gap> AUTODOC_RunPackageScenario( pkgdir, olddir, rec(
> name := "manual-parent-relative",
> makedoc := "../../makedoc.g",
> workdir := "doc/build",
> doc_expected := "tst/manual.expected",
> ) );

# entities option variants
gap> AUTODOC_RunPackageScenario( pkgdir, olddir, rec(
Expand Down
28 changes: 15 additions & 13 deletions tst/manual.expected/_Chapter_Reference.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<Heading>The AutoDoc() function</Heading>

<ManSection>
<Func Arg="[packageOrDirectory], [optrec]" Name="AutoDoc" />
<Func Arg="[pkgdir], [optrec]" Name="AutoDoc" />
<Returns>nothing
</Returns>
<Description>
Expand Down Expand Up @@ -79,27 +79,29 @@
<P/>
The parameters have the following meanings:
<List>
<Mark><A>packageOrDirectory</A></Mark>
<Mark><A>pkgdir</A></Mark>
<Item>
The purpose of this parameter is twofold: to determine the package
This optional parameter is used to determine the package
directory in which &AutoDoc; will operate, and to find the metadata
concerning the package being documented. The parameter is either a
string, an <C>IsDirectory</C> object, or omitted.
If it is a string, &AutoDoc; interprets it as the name of a
package, uses the metadata of the first package known to &GAP;
with that name, and uses the <C>InstallationPath</C> specified in that
metadata as the package directory. If <A>packageOrDirectory</A> is
an <C>IsDirectory</C> object, this is used as package directory;
if the argument is omitted, then the current directory is used.
In the last two cases, the specified directory must contain a
concerning the package being documented. If given, it should be
an <C>IsDirectory</C> object. If the argument is omitted, then &AutoDoc;
checks if it was called from a <F>makedoc.g</F> file or similar, and if so,
uses the directory this is contained in. Otherwise the current
directory is used. In both cases, the specified directory must contain a
<F>PackageInfo.g</F> file, and &AutoDoc; extracts all needed metadata
from that. The <C>IsDirectory</C> form is for example useful if you
have multiple versions of the package around and want to make sure the
documentation of the correct version is built.
<P/>
For backwards compatibility, it is also possible to pass a package name
as this argument, which then is resolved to the package directory of
the first instance of this package &GAP; knows about. However, this is
deprecated, as it is unreliable in the presence of multiple copies of a
package.
<P/>
Note that when using <C>AutoDocWorksheet</C> (see
<Ref Sect='Section_AutoDocWorksheet'/>), there is
no parameter corresponding to <A>packageOrDirectory</A> and so the
no parameter corresponding to <A>pkgdir</A> and so the
<Q>package directory</Q> is always the current directory, and
there is no metadata.
</Item>
Expand Down
13 changes: 7 additions & 6 deletions tst/manual.expected/_Chapter_Tutorials.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ then adopt additional features when useful.
<P/>
Suppose your package is already up and running, but so far has no
manual. Then you can rapidly generate a <Q>scaffold</Q> for a package manual
using the <Ref Func="AutoDoc"/> command like this,
while running &GAP; from within your package's directory (the
one containing the <F>PackageInfo.g</F> file):
using the <Ref Func="AutoDoc"/> command like this:
<Listing><![CDATA[
LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true ) );
]]></Listing>
This first reads the <F>PackageInfo.g</F> file from the current
directory. It extracts information about the package from it
When called from a file such as <F>makedoc.g</F>, &AutoDoc; uses the
directory containing that file as the package directory. Otherwise, it
falls back to the current directory. In either case it then reads the
<F>PackageInfo.g</F> file from that package directory. It extracts information
about the package from it
(such as its name and version, see Section <Ref Sect="Subsection_Tut:Scaffolds:Title"/>).
It then creates two XML files <F>doc/_main.xml</F> and
<F>doc/title.xml</F> inside the package directory. Finally, it runs
Expand Down Expand Up @@ -99,7 +100,7 @@ AutoDoc( rec( autodoc := true ) );
QUIT;
]]></Listing>
Then you can regenerate the package manual from the command line with the
following command, executed from within the package directory:
following command:
<Listing><![CDATA[
gap makedoc.g
]]></Listing>
Expand Down
8 changes: 7 additions & 1 deletion tst/utils.g
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# olddir caller's original working directory, restored on exit
# scenario record describing the scenario to run; it must contain
# `name` and `makedoc`, and may additionally specify:
# - `workdir := "subdir"` to run Read(makedoc) from a nested cwd
# - `stub_gapdoc := true` to skip the expensive GAPDoc post-pass
# - `doc_expected := "tst/...expected"` for full doc-file diffs
# - `tst_expected := "tst/...expected"` for extracted-test diffs
Expand All @@ -16,7 +17,7 @@ AUTODOC_RunPackageScenario := function( pkgdir, olddir, scenario )
local tempdir, docdir, tstdir, ex_dir, files, expected, actual,
old_makegapdocdoc, old_copyhtmlstylefiles, old_manuallab,
old_autodoc_level, old_gapdoc_level, old_warning_level, f,
source_doc_files, source_tst_files;
source_doc_files, source_tst_files, workdir;

tempdir := Filename(
DirectoryTemporary(),
Expand Down Expand Up @@ -88,6 +89,11 @@ AUTODOC_RunPackageScenario := function( pkgdir, olddir, scenario )
SetInfoLevel( InfoAutoDoc, 0 );
SetInfoLevel( InfoGAPDoc, 0 );
SetInfoLevel( InfoWarning, 0 );
if IsBound( scenario.workdir ) then
workdir := Filename( Directory( tempdir ), scenario.workdir );
AUTODOC_CreateDirIfMissing( workdir );
ChangeDirectoryCurrent( workdir );
fi;
Read( scenario.makedoc : nopdf );
SetInfoLevel( InfoAutoDoc, old_autodoc_level );
SetInfoLevel( InfoGAPDoc, old_gapdoc_level );
Expand Down