diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml
index 6eb2a378..e88bc963 100644
--- a/lib/linguist/languages.yml
+++ b/lib/linguist/languages.yml
@@ -620,6 +620,16 @@ Forth:
extensions:
- .4th
+GAP:
+ type: programming
+ lexer: Text only
+ primary_extension: .g
+ extensions:
+ - .g
+ - .gap
+ - .gd
+ - .gi
+
GAS:
type: programming
group: Assembly
diff --git a/lib/linguist/samples.json b/lib/linguist/samples.json
index 6d26388a..8c7ff71f 100644
--- a/lib/linguist/samples.json
+++ b/lib/linguist/samples.json
@@ -129,6 +129,11 @@
".forth",
".fth"
],
+ "GAP": [
+ ".g",
+ ".gd",
+ ".gi"
+ ],
"GAS": [
".s"
],
diff --git a/samples/GAP/Magic.gd b/samples/GAP/Magic.gd
new file mode 100644
index 00000000..cdd8baec
--- /dev/null
+++ b/samples/GAP/Magic.gd
@@ -0,0 +1,307 @@
+#############################################################################
+##
+## Magic.gd AutoDoc package
+##
+## Copyright 2013, Max Horn, JLU Giessen
+## Sebastian Gutsche, University of Kaiserslautern
+##
+#############################################################################
+
+
+#! @Description
+#! This is the main function of the &AutoDoc; package. It can perform
+#! any combination of the following three tasks:
+#!
+#! -
+#! It can (re)generate a scaffold for your package manual.
+#! That is, it can produce two XML files in &GAPDoc; format to be used as part
+#! of your manual: First, a file named doc/PACKAGENAME.xml
+#! (with your package's name substituted) which is used as
+#! main file for the package manual, i.e. this file sets the
+#! XML DOCTYPE and defines various XML entities, includes
+#! other XML files (both those generated by &AutoDoc; as well
+#! as additional files created by other means), tells &GAPDoc;
+#! to generate a table of content and an index, and more.
+#! Secondly, it creates a file doc/title.xml containing a title
+#! page for your documentation, with information about your package
+#! (name, description, version), its authors and more, based
+#! on the data in your PackageInfo.g.
+#!
+#! -
+#! It can scan your package for &AutoDoc; based documentation (by using &AutoDoc;
+#! tags and the Autodoc command.
+#! This will
+#! produce further XML files to be used as part of the package manual.
+#!
+#! -
+#! It can use &GAPDoc; to generate PDF, text and HTML (with
+#! MathJaX enabled) documentation from the &GAPDoc; XML files it
+#! generated as well as additional such files provided by you. For
+#! this, it invokes
+#! to convert the XML sources, and it also instructs &GAPDoc; to copy
+#! supplementary files (such as CSS style files) into your doc directory
+#! (see ).
+#!
+#!
+#! For more information and some examples, please refer to Chapter .
+#!
+#! The parameters have the following meanings:
+#!
+#!
+#! package_name
+#! -
+#! The name of the package whose documentation should be(re)generated.
+#!
+#!
+#!
+#! option_record
+#! -
+#! option_record can be a record with some additional options.
+#! The following are currently supported:
+#!
+#! dir
+#! -
+#! This should be a string containing a (relative) path or a
+#! Directory() object specifying where the package documentation
+#! (i.e. the &GAPDoc; XML files) are stored.
+#!
+#! Default value: "doc/".
+#!
+#! scaffold
+#! -
+#! This controls whether and how to generate scaffold XML files
+#! for the main and title page of the package's documentation.
+#!
+#! The value should be either true, false or a
+#! record. If it is a record or true (the latter is
+#! equivalent to specifying an empty record), then this feature is
+#! enabled. It is also enabled if opt.scaffold is missing but the
+#! package's info record in PackageInfo.g has an AutoDoc entry.
+#! In all other cases (in particular if opt.scaffold is
+#! false), scaffolding is disabled.
+#!
+#!
+#! If opt.scaffold is a record, it may contain the following entries.
+#!
+#### TODO: mention merging with PackageInfo.AutoDoc!
+#!
+#!
+#! includes
+#! -
+#! A list of XML files to be included in the body of the main XML file.
+#! If you specify this list and also are using &AutoDoc; to document
+#! your operations with &AutoDoc; comments,
+#! you can add AutoDocMainFile.xml to this list
+#! to control at which point the documentation produced by &AutoDoc;
+#! is inserted. If you do not do this, it will be added after the last
+#! of your own XML files.
+#!
+#!
+#! appendix
+#! -
+#! 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.
+#!
+#!
+#! bib
+#! -
+#! The name of a bibliography file, in Bibtex or XML format.
+#! If this key is not set, but there is a file doc/PACKAGENAME.bib
+#! then it is assumed that you want to use this as your bibliography.
+#!
+#!
+#### TODO: The 'entities' param is a bit strange. We should probably change it to be a bit more
+#### general, as one might want to define other entities... For now, we do not document it
+#### to leave us the choice of revising how it works.
+####
+#### entities
+#### -
+#### A list of package names or other entities which are used to define corresponding XML entities.
+#### For example, if set to a list containing the string
SomePackage
,
+#### then the following is added to the XML preamble:
+#### SomePackage'>]]>
+#### This allows you to write &SomePackage;
in your documentation
+#### to reference that package. If another type of entity is desired, one can simply add,
+#### instead of a string, add a two entry list a to the list. It will be handled as
+#### a[ 2 ]'>]]>,
+#### so please be careful.
+####
+#!
+#! TitlePage
+#! -
+#! A record whose entries are used to embellish the generated titlepage
+#! for the package manual with extra information, such as a copyright
+#! statement or acknowledgments. To this end, the names of the record
+#! components are used as XML element names, and the values of the
+#! components are outputted as content of these XML elements. For
+#! example, you could pass the following record to set a custom
+#! acknowledgements text:
+#!
+#! For a list of valid entries in the titlepage, please refer to the
+#! &GAPDoc; manual, specifically section
+#! and following.
+#!
+#! document_class
+#! -
+#! Sets the document class of the resulting pdf. The value can either be a string
+#! which has to be the name of the new document class, a list containing this string, or
+#! a list of two strings. Then the first one has to be the document class name, the second one
+#! the option string ( contained in [ ] ) in LaTeX.
+#!
+#! latex_header_file
+#! -
+#! Replaces the standard header from &GAPDoc; completely with the header in this LaTeX file.
+#! Please be careful here, and look at GAPDoc's latexheader.tex file for an example.
+#!
+#! gapdoc_latex_options
+#! -
+#! Must be a record with entries which can be understood by SetGapDocLaTeXOptions. Each entry can be a string, which
+#! will be given to &GAPDoc; directly, or a list containing of two entries: The first one must be the string "file",
+#! the second one a filename. This file will be read and then its content is passed to &GAPDoc; as option with the name
+#! of the entry.
+#!
+#!
+#!
+#!
+#!
+#!
+#! autodoc
+#! -
+#! This controls whether and how to generate addition XML documentation files
+#! by scanning for &AutoDoc; documentation comments.
+#!
+#! The value should be either true, false or a
+#! record. If it is a record or true (the latter is
+#! equivalent to specifying an empty record), then this feature is
+#! enabled. It is also enabled if opt.autodoc is missing but the
+#! package depends (directly) on the &AutoDoc; package.
+#! In all other cases (in particular if opt.autodoc is
+#! false), this feature is disabled.
+#!
+#!
+#! If opt.autodoc is a record, it may contain the following entries.
+#!
+#!
+#!
+#! files
+#! -
+#! A list of files (given by paths relative to the package directory)
+#! to be scanned for &AutoDoc; documentation comments.
+#! Usually it is more convenient to use autodoc.scan_dirs, see below.
+#!
+#!
+#! scan_dirs
+#! -
+#! A list of subdirectories of the package directory (given as relative paths)
+#! which &AutoDoc; then scans for .gi, .gd and .g files; all of these files
+#! are then scanned for &AutoDoc; documentation comments.
+#!
+#! Default value: [ "gap", "lib", "examples", "examples/doc" ].
+#!
+#!
+#! level
+#! -
+#! This defines the level of the created documentation. The default value is 0.
+#! When parts of the manual are declared with a higher value
+#! they will not be printed into the manual.
+#!
+#!
+#### TODO: Document section_intros later on.
+#### However, note that thanks to the new AutoDoc comment syntax, the only remaining
+#### use for this seems to be the ability to specify the order of chapters and
+#### sections.
+#### section_intros
+#### -
+#### TODO.
+####
+#!
+#!
+#!
+#!
+#!
+#! gapdoc
+#! -
+#! This controls whether and how to invoke &GAPDoc; to create HTML, PDF and text
+#! files from your various XML files.
+#!
+#! The value should be either true, false or a
+#! record. If it is a record or true (the latter is
+#! equivalent to specifying an empty record), then this feature is
+#! enabled. It is also enabled if opt.gapdoc is missing.
+#! In all other cases (in particular if opt.gapdoc is
+#! false), this feature is disabled.
+#!
+#!
+#! If opt.gapdoc is a record, it may contain the following entries.
+#!
+#!
+#!
+#!
+#### Note: 'main' is strictly speaking also used for the scaffold.
+#### However, if one uses the scaffolding mechanism, then it is not
+#### really necessary to specify a custom name for the main XML file.
+#### Thus, the purpose of this parameter is to cater for packages
+#### that have existing documentation using a different XML name,
+#### and which do not wish to use scaffolding.
+####
+#### This explain why we only allow specifying gapdoc.main.
+#### The scaffolding code will still honor it, though, just in case.
+#! main
+#! -
+#! The name of the main XML file of the package manual.
+#! This exists primarily to support packages with existing manual
+#! which use a filename here which differs from the default.
+#! In particular, specifying this is unnecessary when using scaffolding.
+#!
+#! Default value: PACKAGENAME.xml.
+#!
+#!
+#! files
+#! -
+#! A list of files (given by paths relative to the package directory)
+#! to be scanned for &GAPDoc; documentation comments.
+#! Usually it is more convenient to use gapdoc.scan_dirs, see below.
+#!
+#!
+#! scan_dirs
+#! -
+#! A list of subdirectories of the package directory (given as relative paths)
+#! which &AutoDoc; then scans for .gi, .gd and .g files; all of these files
+#! are then scanned for &GAPDoc; documentation comments.
+#!
+#! Default value: [ "gap", "lib", "examples", "examples/doc" ].
+#!
+#!
+#!
+#!
+## This is the maketest part. Still under construction.
+#! maketest
+#! -
+#! The maketest item can be true or a record. When it is true,
+#! a simple maketest.g is created in the main package directory,
+#! which can be used to test the examples from the manual. As a record,
+#! the entry can have the following entries itself, to specify some options.
+#!
+#! filename
+#! -
+#! Sets the name of the test file.
+#!
+#! commands
+#! -
+#! A list of strings, each one a command, which
+#! will be executed at the beginning of the test file.
+#!
+#!
+#!
+#!
+#!
+#!
+#!
+#!
+#! @Returns nothing
+#! @Arguments package_name[, option_record ]
+#! @ChapterInfo AutoDoc, The AutoDoc() function
+DeclareGlobalFunction( "AutoDoc" );
+
diff --git a/samples/GAP/Magic.gi b/samples/GAP/Magic.gi
new file mode 100644
index 00000000..5202a1de
--- /dev/null
+++ b/samples/GAP/Magic.gi
@@ -0,0 +1,534 @@
+#############################################################################
+##
+## Magic.gi AutoDoc package
+##
+## Copyright 2013, Max Horn, JLU Giessen
+## Sebastian Gutsche, University of Kaiserslautern
+##
+#############################################################################
+
+# Check if a string has the given suffix or not. Another
+# name for this would "StringEndsWithOtherString".
+# For example, AUTODOC_HasSuffix("file.gi", ".gi") returns
+# true while AUTODOC_HasSuffix("file.txt", ".gi") returns false.
+BindGlobal( "AUTODOC_HasSuffix",
+function(str, suffix)
+ local n, m;
+ n := Length(str);
+ m := Length(suffix);
+ return n >= m and str{[n-m+1..n]} = suffix;
+end );
+
+# Given a string containing a ".", , return its suffix,
+# i.e. the bit after the last ".". For example, given "test.txt",
+# it returns "txt".
+BindGlobal( "AUTODOC_GetSuffix",
+function(str)
+ local i;
+ i := Length(str);
+ while i > 0 and str[i] <> '.' do i := i - 1; od;
+ if i < 0 then return ""; fi;
+ return str{[i+1..Length(str)]};
+end );
+
+# Check whether the given directory exists, and if not, attempt
+# to create it.
+BindGlobal( "AUTODOC_CreateDirIfMissing",
+function(d)
+ local tmp;
+ if not IsDirectoryPath(d) then
+ tmp := CreateDir(d); # Note: CreateDir is currently undocumented
+ if tmp = fail then
+ Error("Cannot create directory ", d, "\n",
+ "Error message: ", LastSystemError().message, "\n");
+ return false;
+ fi;
+ fi;
+ return true;
+end );
+
+
+# Scan the given (by name) subdirs of a package dir for
+# files with one of the given extensions, and return the corresponding
+# filenames, as relative paths (relative to the package dir).
+#
+# For example, the invocation
+# AUTODOC_FindMatchingFiles("AutoDoc", [ "gap/" ], [ "gi", "gd" ]);
+# might return a list looking like
+# [ "gap/AutoDocMainFunction.gd", "gap/AutoDocMainFunction.gi", ... ]
+BindGlobal( "AUTODOC_FindMatchingFiles",
+function (pkg, subdirs, extensions)
+ local d_rel, d, tmp, files, result;
+
+ result := [];
+
+ for d_rel in subdirs do
+ # Get the absolute path to the directory in side the package...
+ d := DirectoriesPackageLibrary( pkg, d_rel );
+ if IsEmpty( d ) then
+ continue;
+ fi;
+ d := d[1];
+ # ... but also keep the relative path (such as "gap")
+ d_rel := Directory( d_rel );
+
+ files := DirectoryContents( d );
+ Sort( files );
+ for tmp in files do
+ if not AUTODOC_GetSuffix( tmp ) in [ "g", "gi", "gd", "autodoc" ] then
+ continue;
+ fi;
+ if not IsReadableFile( Filename( d, tmp ) ) then
+ continue;
+ fi;
+ Add( result, Filename( d_rel, tmp ) );
+ od;
+ od;
+ return result;
+end );
+
+
+# AutoDoc(pkg[, opt])
+#
+## Make this function callable with the package_name AutoDocWorksheet.
+## Which will then create a worksheet!
+InstallGlobalFunction( AutoDoc,
+function( arg )
+ local pkg, package_info, opt, scaffold, gapdoc, maketest,
+ autodoc, pkg_dir, doc_dir, doc_dir_rel, d, tmp,
+ title_page, tree, is_worksheet, position_document_class, i, gapdoc_latex_option_record;
+
+ pkg := arg[1];
+
+ if LowercaseString( pkg ) = "autodocworksheet" then
+ is_worksheet := true;
+ package_info := rec( );
+ pkg_dir := DirectoryCurrent( );
+ else
+ is_worksheet := false;
+ package_info := PackageInfo( pkg )[ 1 ];
+ pkg_dir := DirectoriesPackageLibrary( pkg, "" )[1];
+ fi;
+
+ if Length(arg) >= 2 then
+ opt := arg[2];
+ else
+ opt := rec();
+ fi;
+
+ # Check for certain user supplied options, and if present, add them
+ # to the opt record.
+ tmp := function( key )
+ local val;
+ val := ValueOption( key );
+ if val <> fail then
+ opt.(key) := val;
+ fi;
+ end;
+
+ tmp( "dir" );
+ tmp( "scaffold" );
+ tmp( "autodoc" );
+ tmp( "gapdoc" );
+ tmp( "maketest" );
+
+ #
+ # Setup the output directory
+ #
+ if not IsBound( opt.dir ) then
+ doc_dir := "doc";
+ elif IsString( opt.dir ) or IsDirectory( opt.dir ) then
+ doc_dir := opt.dir;
+ else
+ Error( "opt.dir must be a string containing a path, or a directory object" );
+ fi;
+
+ if IsString( doc_dir ) then
+ # Record the relative version of the path
+ doc_dir_rel := Directory( doc_dir );
+
+ # We intentionally do not use
+ # DirectoriesPackageLibrary( pkg, "doc" )
+ # because it returns an empty list if the subdirectory is missing.
+ # But we want to handle that case by creating the directory.
+ doc_dir := Filename(pkg_dir, doc_dir);
+ doc_dir := Directory(doc_dir);
+
+ else
+ # TODO: doc_dir_rel = ... ?
+ fi;
+
+ # Ensure the output directory exists, create it if necessary
+ AUTODOC_CreateDirIfMissing(Filename(doc_dir, ""));
+
+ # Let the developer know where we are generating the documentation.
+ # This helps diagnose problems where multiple instances of a package
+ # are visible to GAP and the wrong one is used for generating the
+ # documentation.
+ # TODO: Using Info() instead of Print?
+ Print( "Generating documentation in ", doc_dir, "\n" );
+
+ #
+ # Extract scaffolding settings, which can be controlled via
+ # opt.scaffold or package_info.AutoDoc. The former has precedence.
+ #
+ if not IsBound(opt.scaffold) then
+ # Default: enable scaffolding if and only if package_info.AutoDoc is present
+ if IsBound( package_info.AutoDoc ) then
+ scaffold := rec( );
+ fi;
+ elif IsRecord(opt.scaffold) then
+ scaffold := opt.scaffold;
+ elif IsBool(opt.scaffold) then
+ if opt.scaffold = true then
+ scaffold := rec();
+ fi;
+ else
+ Error("opt.scaffold must be a bool or a record");
+ fi;
+
+ # Merge package_info.AutoDoc into scaffold
+ if IsBound(scaffold) and IsBound( package_info.AutoDoc ) then
+ AUTODOC_APPEND_RECORD_WRITEONCE( scaffold, package_info.AutoDoc );
+ fi;
+
+ if IsBound( scaffold ) then
+ AUTODOC_WriteOnce( scaffold, "TitlePage", true );
+ AUTODOC_WriteOnce( scaffold, "MainPage", true );
+ fi;
+
+
+ #
+ # Extract AutoDoc settings
+ #
+ if not IsBound(opt.autodoc) and not is_worksheet then
+ # Enable AutoDoc support if the package depends on AutoDoc.
+ tmp := Concatenation( package_info.Dependencies.NeededOtherPackages,
+ package_info.Dependencies.SuggestedOtherPackages );
+ if ForAny( tmp, x -> LowercaseString(x[1]) = "autodoc" ) then
+ autodoc := rec();
+ fi;
+ elif IsRecord(opt.autodoc) then
+ autodoc := opt.autodoc;
+ elif IsBool(opt.autodoc) and opt.autodoc = true then
+ autodoc := rec();
+ fi;
+
+ if IsBound(autodoc) then
+ if not IsBound( autodoc.files ) then
+ autodoc.files := [ ];
+ fi;
+
+ if not IsBound( autodoc.scan_dirs ) and not is_worksheet then
+ autodoc.scan_dirs := [ "gap", "lib", "examples", "examples/doc" ];
+ elif not IsBound( autodoc.scan_dirs ) and is_worksheet then
+ autodoc.scan_dirs := [ ];
+ fi;
+
+ if not IsBound( autodoc.level ) then
+ autodoc.level := 0;
+ fi;
+
+ PushOptions( rec( level_value := autodoc.level ) );
+
+ if not is_worksheet then
+ Append( autodoc.files, AUTODOC_FindMatchingFiles(pkg, autodoc.scan_dirs, [ "g", "gi", "gd" ]) );
+ fi;
+ fi;
+
+ #
+ # Extract GAPDoc settings
+ #
+ if not IsBound( opt.gapdoc ) then
+ # Enable GAPDoc support by default
+ gapdoc := rec();
+ elif IsRecord( opt.gapdoc ) then
+ gapdoc := opt.gapdoc;
+ elif IsBool( opt.gapdoc ) and opt.gapdoc = true then
+ gapdoc := rec();
+ fi;
+
+ #
+ # Extract test settings
+ #
+
+ if IsBound( opt.maketest ) then
+ if IsRecord( opt.maketest ) then
+ maketest := opt.maketest;
+ elif opt.maketest = true then
+ maketest := rec( );
+ fi;
+ fi;
+
+ if IsBound( gapdoc ) then
+
+ if not IsBound( gapdoc.main ) then
+ gapdoc.main := pkg;
+ fi;
+
+ # FIXME: the following may break if a package uses more than one book
+ if IsBound( package_info.PackageDoc ) and IsBound( package_info.PackageDoc[1].BookName ) then
+ gapdoc.bookname := package_info.PackageDoc[1].BookName;
+ elif not is_worksheet then
+ # Default: book name = package name
+ gapdoc.bookname := pkg;
+
+ Print("\n");
+ Print("WARNING: PackageInfo.g is missing a PackageDoc entry!\n");
+ Print("Without this, your package manual will not be recognized by the GAP help system.\n");
+ Print("You can correct this by adding the following to your PackageInfo.g:\n");
+ Print("PackageDoc := rec(\n");
+ Print(" BookName := ~.PackageName,\n");
+ #Print(" BookName := \"", pkg, "\",\n");
+ Print(" ArchiveURLSubset := [\"doc\"],\n");
+ Print(" HTMLStart := \"doc/chap0.html\",\n");
+ Print(" PDFFile := \"doc/manual.pdf\",\n");
+ Print(" SixFile := \"doc/manual.six\",\n");
+ Print(" LongTitle := ~.Subtitle,\n");
+ Print("),\n");
+ Print("\n");
+ fi;
+
+ if not IsBound( gapdoc.files ) then
+ gapdoc.files := [];
+ fi;
+
+ if not IsBound( gapdoc.scan_dirs ) and not is_worksheet then
+ gapdoc.scan_dirs := [ "gap", "lib", "examples", "examples/doc" ];
+ fi;
+
+ if not is_worksheet then
+ Append( gapdoc.files, AUTODOC_FindMatchingFiles(pkg, gapdoc.scan_dirs, [ "g", "gi", "gd" ]) );
+ fi;
+
+ # Attempt to weed out duplicates as they may confuse GAPDoc (this
+ # won't work if there are any non-normalized paths in the list).
+ gapdoc.files := Set( gapdoc.files );
+
+ # Convert the file paths in gapdoc.files, which are relative to
+ # the package directory, to paths which are relative to the doc directory.
+ # For this, we assume that doc_dir_rel is normalized (e.g.
+ # it does not contains '//') and relative.
+ d := Number( Filename( doc_dir_rel, "" ), x -> x = '/' );
+ d := Concatenation( ListWithIdenticalEntries(d, "../") );
+ gapdoc.files := List( gapdoc.files, f -> Concatenation( d, f ) );
+ fi;
+
+
+ # read tree
+ # FIXME: shouldn't tree be declared inside of an 'if IsBound(autodoc)' section?
+ tree := DocumentationTree( );
+
+ if IsBound( autodoc ) then
+ if IsBound( autodoc.section_intros ) then
+ AUTODOC_PROCESS_INTRO_STRINGS( autodoc.section_intros : Tree := tree );
+ fi;
+
+ AutoDocScanFiles( autodoc.files : PackageName := pkg, Tree := tree );
+ fi;
+
+ if is_worksheet then
+ # FIXME: We use scaffold and autodoc here without checking whether
+ # they are bound. Does that mean worksheets always use them?
+ if IsRecord( scaffold.TitlePage ) and IsBound( scaffold.TitlePage.Title ) then
+ pkg := scaffold.TitlePage.Title;
+
+ elif IsBound( tree!.TitlePage.Title ) then
+ pkg := tree!.TitlePage.Title;
+
+ elif IsBound( autodoc.files ) and Length( autodoc.files ) > 0 then
+ pkg := autodoc.files[ 1 ];
+
+ while Position( pkg, '/' ) <> fail do
+ Remove( pkg, 1 );
+ od;
+
+ while Position( pkg, '.' ) <> fail do
+ Remove( pkg, Length( pkg ) );
+ od;
+
+ else
+ Error( "could not figure out a title." );
+ fi;
+
+ if not IsString( pkg ) then
+ pkg := JoinStringsWithSeparator( pkg, " " );
+ fi;
+
+ gapdoc.main := ReplacedString( pkg, " ", "_" );
+ gapdoc.bookname := ReplacedString( pkg, " ", "_" );
+ fi;
+
+ #
+ # Generate scaffold
+ #
+ gapdoc_latex_option_record := rec( );
+
+ if IsBound( scaffold ) then
+ ## Syntax is [ "class", [ "options" ] ]
+ if IsBound( scaffold.document_class ) then
+ position_document_class := PositionSublist( GAPDoc2LaTeXProcs.Head, "documentclass" );
+
+ if IsString( scaffold.document_class ) then
+ scaffold.document_class := [ scaffold.document_class ];
+ fi;
+
+ if position_document_class = fail then
+ Error( "something is wrong with the LaTeX header" );
+ fi;
+
+ GAPDoc2LaTeXProcs.Head := Concatenation(
+ GAPDoc2LaTeXProcs.Head{[ 1 .. PositionSublist( GAPDoc2LaTeXProcs.Head, "{", position_document_class ) ]},
+ scaffold.document_class[ 1 ],
+ GAPDoc2LaTeXProcs.Head{[ PositionSublist( GAPDoc2LaTeXProcs.Head, "}", position_document_class ) .. Length( GAPDoc2LaTeXProcs.Head ) ]} );
+
+ if Length( scaffold.document_class ) = 2 then
+
+ GAPDoc2LaTeXProcs.Head := Concatenation(
+ GAPDoc2LaTeXProcs.Head{[ 1 .. PositionSublist( GAPDoc2LaTeXProcs.Head, "[", position_document_class ) ]},
+ scaffold.document_class[ 2 ],
+ GAPDoc2LaTeXProcs.Head{[ PositionSublist( GAPDoc2LaTeXProcs.Head, "]", position_document_class ) .. Length( GAPDoc2LaTeXProcs.Head ) ]} );
+ fi;
+ fi;
+
+ if IsBound( scaffold.latex_header_file ) then
+ GAPDoc2LaTeXProcs.Head := StringFile( scaffold.latex_header_file );
+ fi;
+
+ if IsBound( scaffold.gapdoc_latex_options ) then
+ if IsRecord( scaffold.gapdoc_latex_options ) then
+ for i in RecNames( scaffold.gapdoc_latex_options ) do
+ if not IsString( scaffold.gapdoc_latex_options.( i ) )
+ and IsList( scaffold.gapdoc_latex_options.( i ) )
+ and LowercaseString( scaffold.gapdoc_latex_options.( i )[ 1 ] ) = "file" then
+ scaffold.gapdoc_latex_options.( i ) := StringFile( scaffold.gapdoc_latex_options.( i )[ 2 ] );
+ fi;
+ od;
+
+ gapdoc_latex_option_record := scaffold.gapdoc_latex_options;
+ fi;
+ fi;
+
+ if not IsBound( scaffold.includes ) then
+ scaffold.includes := [ ];
+ fi;
+
+ if IsBound( autodoc ) then
+ # If scaffold.includes is already set, then we add
+ # AutoDocMainFile.xml to it, but *only* if it not already
+ # there. This way, package authors can control where
+ # it is put in their includes list.
+ if not "AutoDocMainFile.xml" in scaffold.includes then
+ Add( scaffold.includes, "AutoDocMainFile.xml" );
+ fi;
+ fi;
+
+ if IsBound( scaffold.bib ) and IsBool( scaffold.bib ) then
+ if scaffold.bib = true then
+ scaffold.bib := Concatenation( pkg, ".bib" );
+ else
+ Unbind( scaffold.bib );
+ fi;
+ elif not IsBound( scaffold.bib ) then
+ # If there is a doc/PKG.bib file, assume that we want to reference it in the scaffold.
+ if IsReadableFile( Filename( doc_dir, Concatenation( pkg, ".bib" ) ) ) then
+ scaffold.bib := Concatenation( pkg, ".bib" );
+ fi;
+ fi;
+
+ AUTODOC_WriteOnce( scaffold, "index", true );
+
+ if IsBound( gapdoc ) then
+ if AUTODOC_GetSuffix( gapdoc.main ) = "xml" then
+ scaffold.main_xml_file := gapdoc.main;
+ else
+ scaffold.main_xml_file := Concatenation( gapdoc.main, ".xml" );
+ fi;
+ fi;
+
+ # TODO: It should be possible to only rebuild the title page. (Perhaps also only the main page? but this is less important)
+ if IsBound( scaffold.TitlePage ) then
+ if IsRecord( scaffold.TitlePage ) then
+ title_page := scaffold.TitlePage;
+ else
+ title_page := rec( );
+ fi;
+
+ AUTODOC_WriteOnce( title_page, "dir", doc_dir );
+ AUTODOC_APPEND_RECORD_WRITEONCE( title_page, tree!.TitlePage );
+
+ if not is_worksheet then
+ AUTODOC_APPEND_RECORD_WRITEONCE( title_page, ExtractTitleInfoFromPackageInfo( pkg ) );
+ fi;
+
+ CreateTitlePage( title_page );
+ fi;
+
+ if IsBound( scaffold.MainPage ) and scaffold.MainPage <> false then
+ scaffold.dir := doc_dir;
+ scaffold.book_name := pkg;
+ CreateMainPage( scaffold );
+ fi;
+ fi;
+
+ #
+ # Run AutoDoc
+ #
+ if IsBound( autodoc ) then
+ WriteDocumentation( tree, doc_dir );
+ fi;
+
+
+ #
+ # Run GAPDoc
+ #
+ if IsBound( gapdoc ) then
+
+ # Ask GAPDoc to use UTF-8 as input encoding for LaTeX, as the XML files
+ # of the documentation are also in UTF-8 encoding, and may contain characters
+ # not contained in the default Latin 1 encoding.
+ SetGapDocLaTeXOptions( "utf8", gapdoc_latex_option_record );
+
+ MakeGAPDocDoc( doc_dir, gapdoc.main, gapdoc.files, gapdoc.bookname, "MathJax" );
+
+ CopyHTMLStyleFiles( Filename( doc_dir, "" ) );
+
+ # The following (undocumented) API is there for compatibility
+ # with old-style gapmacro.tex based package manuals. It
+ # produces a manual.lab file which those packages can use if
+ # they wish to link to things in the manual we are currently
+ # generating. This can probably be removed eventually, but for
+ # now, doing it does not hurt.
+
+ # FIXME: It seems that this command does not work if pdflatex
+ # is not present. Maybe we should remove it.
+
+ if not is_worksheet then
+ GAPDocManualLab( pkg );
+ fi;
+
+ fi;
+
+ if IsBound( maketest ) then
+
+ AUTODOC_WriteOnce( maketest, "filename", "maketest.g" );
+ AUTODOC_WriteOnce( maketest, "folder", pkg_dir );
+ AUTODOC_WriteOnce( maketest, "scan_dir", doc_dir );
+ AUTODOC_WriteOnce( maketest, "files_to_scan", gapdoc.files );
+
+ if IsString( maketest.folder ) then
+ maketest.folder := Directory( maketest.folder );
+ fi;
+
+ if IsString( maketest.scan_dir ) then
+ maketest.scan_dir := Directory( maketest.scan_dir );
+ fi;
+
+ AUTODOC_WriteOnce( maketest, "commands", [ ] );
+ AUTODOC_WriteOnce( maketest, "book_name", gapdoc.main );
+
+ CreateMakeTest( maketest );
+ fi;
+
+ return true;
+end );
diff --git a/samples/GAP/PackageInfo.g b/samples/GAP/PackageInfo.g
new file mode 100644
index 00000000..68e5ecdb
--- /dev/null
+++ b/samples/GAP/PackageInfo.g
@@ -0,0 +1,115 @@
+#############################################################################
+##
+## PackageInfo.g for the package `cvec' Max Neunhoeffer
+##
+## (created from Frank Lübeck's PackageInfo.g template file)
+##
+
+SetPackageInfo( rec(
+
+PackageName := "cvec",
+Subtitle := "Compact vectors over finite fields",
+Version := "2.5.1",
+Date := "04/04/2014", # dd/mm/yyyy format
+
+## Information about authors and maintainers.
+Persons := [
+ rec(
+ LastName := "Neunhoeffer",
+ FirstNames := "Max",
+ IsAuthor := true,
+ IsMaintainer := false,
+ Email := "neunhoef@mcs.st-and.ac.uk",
+ WWWHome := "http://www-groups.mcs.st-and.ac.uk/~neunhoef/",
+ PostalAddress := Concatenation( [
+ "School of Mathematics and Statistics\n",
+ "University of St Andrews\n",
+ "Mathematical Institute\n",
+ "North Haugh\n",
+ "St Andrews, Fife KY16 9SS\n",
+ "Scotland, UK" ] ),
+ Place := "St Andrews",
+ Institution := "University of St Andrews"
+ ),
+],
+
+## Status information. Currently the following cases are recognized:
+## "accepted" for successfully refereed packages
+## "deposited" for packages for which the GAP developers agreed
+## to distribute them with the core GAP system
+## "dev" for development versions of packages
+## "other" for all other packages
+##
+# Status := "accepted",
+Status := "deposited",
+
+## You must provide the next two entries if and only if the status is
+## "accepted" because is was successfully refereed:
+# format: 'name (place)'
+# CommunicatedBy := "Mike Atkinson (St. Andrews)",
+#CommunicatedBy := "",
+# format: mm/yyyy
+# AcceptDate := "08/1999",
+#AcceptDate := "",
+
+PackageWWWHome := "http://neunhoef.github.io/cvec/",
+README_URL := Concatenation(~.PackageWWWHome, "README"),
+PackageInfoURL := Concatenation(~.PackageWWWHome, "PackageInfo.g"),
+ArchiveURL := Concatenation("https://github.com/neunhoef/cvec/",
+ "releases/download/v", ~.Version,
+ "/cvec-", ~.Version),
+ArchiveFormats := ".tar.gz .tar.bz2",
+
+## Here you must provide a short abstract explaining the package content
+## in HTML format (used on the package overview Web page) and an URL
+## for a Webpage with more detailed information about the package
+## (not more than a few lines, less is ok):
+## Please, use 'GAP' and
+## 'MyPKG' for specifing package names.
+##
+AbstractHTML :=
+ "This package provides an implementation of compact vectors over finite\
+ fields. Contrary to earlier implementations no table lookups are used\
+ but only word-based processor arithmetic. This allows for bigger finite\
+ fields and higher speed.",
+
+PackageDoc := rec(
+ BookName := "cvec",
+ ArchiveURLSubset := ["doc"],
+ HTMLStart := "doc/chap0.html",
+ PDFFile := "doc/manual.pdf",
+ SixFile := "doc/manual.six",
+ LongTitle := "Compact vectors over finite fields",
+),
+
+Dependencies := rec(
+ GAP := ">=4.5.5",
+ NeededOtherPackages := [
+ ["GAPDoc", ">= 1.2"],
+ ["IO", ">= 4.1"],
+ ["orb", ">= 4.2"],
+ ],
+ SuggestedOtherPackages := [],
+ ExternalConditions := []
+),
+
+AvailabilityTest := function()
+ if not "cvec" in SHOW_STAT() and
+ Filename(DirectoriesPackagePrograms("cvec"), "cvec.so") = fail then
+ #Info(InfoWarning, 1, "cvec: kernel cvec functions not available.");
+ return fail;
+ fi;
+ return true;
+end,
+
+## *Optional*, but recommended: path relative to package root to a file which
+## contains as many tests of the package functionality as sensible.
+#TestFile := "tst/testall.g",
+
+## *Optional*: Here you can list some keyword related to the topic
+## of the package.
+Keywords := []
+
+));
+
+
diff --git a/samples/GAP/example.gd b/samples/GAP/example.gd
new file mode 100644
index 00000000..c285ea32
--- /dev/null
+++ b/samples/GAP/example.gd
@@ -0,0 +1,23 @@
+#############################################################################
+##
+#W example.gd
+##
+## This file contains a sample of a GAP declaration file.
+##
+DeclareProperty( "SomeProperty", IsLeftModule );
+DeclareGlobalFunction( "SomeGlobalFunction" );
+
+
+#############################################################################
+##
+#C IsQuuxFrobnicator()
+##
+##
+##
+##
+##
+## Tests whether R is a quux frobnicator.
+##
+##
+##
+DeclareSynonym( "IsQuuxFrobnicator", IsField and IsGroup );
diff --git a/samples/GAP/example.gi b/samples/GAP/example.gi
new file mode 100644
index 00000000..c9c5e55d
--- /dev/null
+++ b/samples/GAP/example.gi
@@ -0,0 +1,64 @@
+#############################################################################
+##
+#W example.gd
+##
+## This file contains a sample of a GAP implementation file.
+##
+
+
+#############################################################################
+##
+#M SomeOperation( )
+##
+## performs some operation on
+##
+InstallMethod( SomeProperty,
+ "for left modules",
+ [ IsLeftModule ], 0,
+ function( M )
+ if IsFreeLeftModule( M ) and not IsTrivial( M ) then
+ return true;
+ fi;
+ TryNextMethod();
+ end );
+
+
+
+#############################################################################
+##
+#F SomeGlobalFunction( )
+##
+## A global variadic funfion.
+##
+InstallGlobalFunction( SomeGlobalFunction, function( arg )
+ if Length( arg ) = 3 then
+ return arg[1] + arg[2] * arg[3];
+ elif Length( arg ) = 2 then
+ return arg[1] - arg[2]
+ else
+ Error( "usage: SomeGlobalFunction( , [, ] )" );
+ fi;
+ end );
+
+
+#
+# A plain function.
+#
+SomeFunc := function(x, y)
+ local z, func, tmp, j;
+ z := x * 1.0;
+ y := 17^17 - y;
+ func := a -> a mod 5;
+ tmp := List( [1..50], func );
+ while y > 0 do
+ for j in tmp do
+ Print(j, "\n");
+ od;
+ repeat
+ y := y - 1;
+ until 0 < 1;
+ y := y -1;
+ od;
+ return z;
+end;
+
\ No newline at end of file
diff --git a/samples/GAP/vspc.gd b/samples/GAP/vspc.gd
new file mode 100644
index 00000000..d381e6f1
--- /dev/null
+++ b/samples/GAP/vspc.gd
@@ -0,0 +1,822 @@
+#############################################################################
+##
+#W vspc.gd GAP library Thomas Breuer
+##
+##
+#Y Copyright (C) 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
+#Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
+#Y Copyright (C) 2002 The GAP Group
+##
+## This file declares the operations for vector spaces.
+##
+## The operations for bases of free left modules can be found in the file
+## lib/basis.gd.
+##
+
+
+#############################################################################
+##
+#C IsLeftOperatorRing()
+##
+##
+##
+##
+##
+##
+##
+##
+DeclareSynonym( "IsLeftOperatorRing",
+ IsLeftOperatorAdditiveGroup and IsRing and IsAssociativeLOpDProd );
+#T really?
+
+
+#############################################################################
+##
+#C IsLeftOperatorRingWithOne()
+##
+##
+##
+##
+##
+##
+##
+##
+DeclareSynonym( "IsLeftOperatorRingWithOne",
+ IsLeftOperatorAdditiveGroup and IsRingWithOne
+ and IsAssociativeLOpDProd );
+#T really?
+
+
+#############################################################################
+##
+#C IsLeftVectorSpace( )
+#C IsVectorSpace( )
+##
+## <#GAPDoc Label="IsLeftVectorSpace">
+##
+##
+##
+##
+##
+## A vector space in &GAP; is a free left module
+## (see ) over a division ring
+## (see Chapter ).
+##
+## Whenever we talk about an F-vector space V then V is
+## an additive group (see ) on which the
+## division ring F acts via multiplication from the left such that
+## this action and the addition in V are left and right distributive.
+## The division ring F can be accessed as value of the attribute
+## .
+##
+## Vector spaces in &GAP; are always left vector spaces,
+## and are
+## synonyms.
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "IsLeftVectorSpace",
+ IsLeftModule and IsLeftActedOnByDivisionRing );
+
+DeclareSynonym( "IsVectorSpace", IsLeftVectorSpace );
+
+InstallTrueMethod( IsFreeLeftModule,
+ IsLeftModule and IsLeftActedOnByDivisionRing );
+
+
+#############################################################################
+##
+#F IsGaussianSpace( )
+##
+## <#GAPDoc Label="IsGaussianSpace">
+##
+##
+##
+##
+## The filter (see )
+## for the row space (see )
+## or matrix space (see ) V
+## over the field F, say,
+## indicates that the entries of all row vectors or matrices in V,
+## respectively, are all contained in F.
+## In this case, V is called a Gaussian vector space.
+## Bases for Gaussian spaces can be computed using Gaussian elimination for
+## a given list of vector space generators.
+## mats:= [ [[1,1],[2,2]], [[3,4],[0,1]] ];;
+## gap> V:= VectorSpace( Rationals, mats );;
+## gap> IsGaussianSpace( V );
+## true
+## gap> mats[1][1][1]:= E(4);; # an element in an extension field
+## gap> V:= VectorSpace( Rationals, mats );;
+## gap> IsGaussianSpace( V );
+## false
+## gap> V:= VectorSpace( Field( Rationals, [ E(4) ] ), mats );;
+## gap> IsGaussianSpace( V );
+## true
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareFilter( "IsGaussianSpace", IsVectorSpace );
+
+InstallTrueMethod( IsGaussianSpace,
+ IsVectorSpace and IsFullMatrixModule );
+
+InstallTrueMethod( IsGaussianSpace,
+ IsVectorSpace and IsFullRowModule );
+
+
+#############################################################################
+##
+#C IsDivisionRing( )
+##
+## <#GAPDoc Label="IsDivisionRing">
+##
+##
+##
+##
+## A division ring in &GAP; is a nontrivial associative algebra
+## D with a multiplicative inverse for each nonzero element.
+## In &GAP; every division ring is a vector space over a division ring
+## (possibly over itself).
+## Note that being a division ring is thus not a property that a ring can
+## get, because a ring is usually not represented as a vector space.
+##
+## The field of coefficients is stored as the value of the attribute
+## of D.
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonymAttr( "IsDivisionRing",
+ IsMagmaWithInversesIfNonzero
+ and IsLeftOperatorRingWithOne
+ and IsLeftVectorSpace
+ and IsNonTrivial
+ and IsAssociative
+ and IsEuclideanRing );
+
+
+#############################################################################
+##
+#A GeneratorsOfLeftVectorSpace( )
+#A GeneratorsOfVectorSpace( )
+##
+## <#GAPDoc Label="GeneratorsOfLeftVectorSpace">
+##
+##
+##
+##
+##
+## For an F-vector space V,
+## returns a list of vectors in
+## V that generate V as an F-vector space.
+## GeneratorsOfVectorSpace( FullRowSpace( Rationals, 3 ) );
+## [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonymAttr( "GeneratorsOfLeftVectorSpace",
+ GeneratorsOfLeftOperatorAdditiveGroup );
+
+DeclareSynonymAttr( "GeneratorsOfVectorSpace",
+ GeneratorsOfLeftOperatorAdditiveGroup );
+
+
+#############################################################################
+##
+#A CanonicalBasis( )
+##
+## <#GAPDoc Label="CanonicalBasis">
+##
+##
+##
+##
+## If the vector space V supports a canonical basis then
+## returns this basis,
+## otherwise fail is returned.
+##
+## The defining property of a canonical basis is that its vectors are
+## uniquely determined by the vector space.
+## If canonical bases exist for two vector spaces over the same left acting
+## domain (see ) then the equality of
+## these vector spaces can be decided by comparing the canonical bases.
+##
+## The exact meaning of a canonical basis depends on the type of V.
+## Canonical bases are defined for example for Gaussian row and matrix
+## spaces (see ).
+##
+## If one designs a new kind of vector spaces
+## (see ) and
+## defines a canonical basis for these spaces then the
+## method one installs
+## (see )
+## must not call .
+## On the other hand, one probably should install a
+## method that simply calls ,
+## the value of the method
+## (see and
+## )
+## being CANONICAL_BASIS_FLAGS.
+## vecs:= [ [ 1, 2, 3 ], [ 1, 1, 1 ], [ 1, 1, 1 ] ];;
+## gap> V:= VectorSpace( Rationals, vecs );;
+## gap> B:= CanonicalBasis( V );
+## CanonicalBasis( )
+## gap> BasisVectors( B );
+## [ [ 1, 0, -1 ], [ 0, 1, 2 ] ]
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareAttribute( "CanonicalBasis", IsFreeLeftModule );
+
+
+#############################################################################
+##
+#F IsRowSpace( )
+##
+## <#GAPDoc Label="IsRowSpace">
+##
+##
+##
+##
+## A row space in &GAP; is a vector space that consists of
+## row vectors (see Chapter ).
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "IsRowSpace", IsRowModule and IsVectorSpace );
+
+
+#############################################################################
+##
+#F IsGaussianRowSpace( )
+##
+##
+##
+##
+##
+## A row space is Gaussian if the left acting domain contains all
+## scalars that occur in the vectors.
+## Thus one can use Gaussian elimination in the calculations.
+##
+## (Otherwise the space is non-Gaussian.
+## We will need a flag for this to write down methods that delegate from
+## non-Gaussian spaces to Gaussian ones.)
+##
+##
+##
+##
+DeclareSynonym( "IsGaussianRowSpace", IsGaussianSpace and IsRowSpace );
+
+
+#############################################################################
+##
+#F IsNonGaussianRowSpace( )
+##
+##
+##
+##
+##
+## If an F-vector space V is in the filter
+## then this expresses that V
+## consists of row vectors (see ) such
+## that not all entries in these row vectors are contained in F
+## (so Gaussian elimination cannot be used to compute an F-basis
+## from a list of vector space generators),
+## and that V is handled via the mechanism of nice bases
+## (see ) in the following way.
+## Let K be the field spanned by the entries of all vectors in
+## V.
+## Then the value of V is
+## a basis B of the field extension K / ( K \cap F ),
+## and the value of v \in V
+## is defined by replacing each entry of v by the list of its
+## B-coefficients, and then forming the concatenation.
+##
+## So the associated nice vector space is a Gaussian row space
+## (see ).
+##
+##
+##
+DeclareHandlingByNiceBasis( "IsNonGaussianRowSpace",
+ "for non-Gaussian row spaces" );
+
+
+#############################################################################
+##
+#F IsMatrixSpace( )
+##
+## <#GAPDoc Label="IsMatrixSpace">
+##
+##
+##
+##
+## A matrix space in &GAP; is a vector space that consists of matrices
+## (see Chapter ).
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "IsMatrixSpace", IsMatrixModule and IsVectorSpace );
+
+
+#############################################################################
+##
+#F IsGaussianMatrixSpace( )
+##
+##
+##
+##
+##
+## A matrix space is Gaussian if the left acting domain contains all
+## scalars that occur in the vectors.
+## Thus one can use Gaussian elimination in the calculations.
+##
+## (Otherwise the space is non-Gaussian.
+## We will need a flag for this to write down methods that delegate from
+## non-Gaussian spaces to Gaussian ones.)
+##
+##
+##
+DeclareSynonym( "IsGaussianMatrixSpace", IsGaussianSpace and IsMatrixSpace );
+
+
+#############################################################################
+##
+#F IsNonGaussianMatrixSpace( )
+##
+##
+##
+##
+##
+## If an F-vector space V is in the filter
+##
+## then this expresses that V consists of matrices
+## (see )
+## such that not all entries in these matrices are contained in F
+## (so Gaussian elimination cannot be used to compute an F-basis
+## from a list of vector space generators),
+## and that V is handled via the mechanism of nice bases
+## (see ) in the following way.
+## Let K be the field spanned by the entries of all vectors in V.
+## The value of V is irrelevant,
+## and the value of v \in V
+## is defined as the concatenation of the rows of v.
+##
+## So the associated nice vector space is a (not necessarily Gaussian)
+## row space (see ).
+##
+##
+##
+DeclareHandlingByNiceBasis( "IsNonGaussianMatrixSpace",
+ "for non-Gaussian matrix spaces" );
+
+
+#############################################################################
+##
+#A NormedRowVectors( ) . . . normed vectors in a Gaussian row space
+##
+## <#GAPDoc Label="NormedRowVectors">
+##
+##
+##
+##
+## For a finite Gaussian row space V
+## (see , ),
+## returns a list of those nonzero
+## vectors in V that have a one in the first nonzero component.
+##
+## The result list can be used as action domain for the action of a matrix
+## group via , which yields the natural action on
+## one-dimensional subspaces of V
+## (see also ).
+## vecs:= NormedRowVectors( GF(3)^2 );
+## [ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3) ], [ Z(3)^0, Z(3)^0 ],
+## [ Z(3)^0, Z(3) ] ]
+## gap> Action( GL(2,3), vecs, OnLines );
+## Group([ (3,4), (1,2,4) ])
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareAttribute( "NormedRowVectors", IsGaussianSpace );
+
+
+#############################################################################
+##
+#A TrivialSubspace( )
+##
+## <#GAPDoc Label="TrivialSubspace">
+##
+##
+##
+##
+## For a vector space V, returns the
+## subspace of V that consists of the zero vector in V.
+## V:= GF(3)^3;;
+## gap> triv:= TrivialSubspace( V );
+##
+## gap> AsSet( triv );
+## [ [ 0*Z(3), 0*Z(3), 0*Z(3) ] ]
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonymAttr( "TrivialSubspace", TrivialSubmodule );
+
+
+#############################################################################
+##
+#F VectorSpace( , [, ][, "basis"] )
+##
+## <#GAPDoc Label="VectorSpace">
+##
+##
+##
+##
+## For a field F and a collection gens of vectors,
+## returns the F-vector space spanned by
+## the elements in gens.
+##
+## The optional argument zero can be used to specify the zero element
+## of the space; zero must be given if gens is empty.
+## The optional string "basis" indicates that gens is known to
+## be linearly independent over F, in particular the dimension of the
+## vector space is immediately set;
+## note that need not return the basis formed by
+## gens if the string "basis" is given as an argument.
+##
+## V:= VectorSpace( Rationals, [ [ 1, 2, 3 ], [ 1, 1, 1 ] ] );
+##
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareGlobalFunction( "VectorSpace" );
+
+
+#############################################################################
+##
+#F Subspace( , [, "basis"] ) . subspace of generated by
+#F SubspaceNC( , [, "basis"] )
+##
+## <#GAPDoc Label="Subspace">
+##
+##
+##
+##
+##
+## For an F-vector space V and a list or collection
+## gens that is a subset of V,
+## returns the F-vector space spanned by
+## gens; if gens is empty then the trivial subspace
+## (see ) of V is returned.
+## The parent (see ) of the returned vector space
+## is set to V.
+##
+## does the same as ,
+## except that it omits the check whether gens is a subset of
+## V.
+##
+## The optional string "basis" indicates that gens is known to
+## be linearly independent over F.
+## In this case the dimension of the subspace is immediately set,
+## and both and do
+## not check whether gens really is linearly independent and
+## whether gens is a subset of V.
+##
+## V:= VectorSpace( Rationals, [ [ 1, 2, 3 ], [ 1, 1, 1 ] ] );;
+## gap> W:= Subspace( V, [ [ 0, 1, 2 ] ] );
+##
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "Subspace", Submodule );
+
+DeclareSynonym( "SubspaceNC", SubmoduleNC );
+
+
+#############################################################################
+##
+#O AsVectorSpace( , ) . . . . . . . . . view as -vector space
+##
+## <#GAPDoc Label="AsVectorSpace">
+##
+##
+##
+##
+## Let F be a division ring and D a domain.
+## If the elements in D form an F-vector space then
+## returns this F-vector space,
+## otherwise fail is returned.
+##
+## can be used for example to view a given
+## vector space as a vector space over a smaller or larger division ring.
+## V:= FullRowSpace( GF( 27 ), 3 );
+## ( GF(3^3)^3 )
+## gap> Dimension( V ); LeftActingDomain( V );
+## 3
+## GF(3^3)
+## gap> W:= AsVectorSpace( GF( 3 ), V );
+##
+## gap> Dimension( W ); LeftActingDomain( W );
+## 9
+## GF(3)
+## gap> AsVectorSpace( GF( 9 ), V );
+## fail
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "AsVectorSpace", AsLeftModule );
+
+
+#############################################################################
+##
+#O AsSubspace( , ) . . . . . . . . . . . view as subspace of
+##
+## <#GAPDoc Label="AsSubspace">
+##
+##
+##
+##
+## Let V be an F-vector space, and U a collection.
+## If U is a subset of V such that the elements of U
+## form an F-vector space then returns this
+## vector space, with parent set to V
+## (see ).
+## Otherwise fail is returned.
+## V:= VectorSpace( Rationals, [ [ 1, 2, 3 ], [ 1, 1, 1 ] ] );;
+## gap> W:= VectorSpace( Rationals, [ [ 1/2, 1/2, 1/2 ] ] );;
+## gap> U:= AsSubspace( V, W );
+##
+## gap> Parent( U ) = V;
+## true
+## gap> AsSubspace( V, [ [ 1, 1, 1 ] ] );
+## fail
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareOperation( "AsSubspace", [ IsVectorSpace, IsCollection ] );
+
+
+#############################################################################
+##
+#F Intersection2Spaces( , , )
+##
+##
+##
+##
+##
+## is a function that takes two arguments V and W which must
+## be finite dimensional vector spaces,
+## and returns the intersection of V and W.
+##
+## If the left acting domains are different then let F be their
+## intersection.
+## The intersection of V and W is computed as intersection of
+## AsStruct( F, V ) and
+## AsStruct( F, V ).
+##
+## If the left acting domains are equal to F then the intersection of
+## V and W is returned either as F-Substruct
+## with the common parent of V and W or as
+## F-Struct, in both cases with known basis.
+##
+## This function is used to handle the intersections of two vector spaces,
+## two algebras, two algebras-with-one, two left ideals, two right ideals,
+## two two-sided ideals.
+##
+##
+##
+DeclareGlobalFunction( "Intersection2Spaces" );
+
+
+#############################################################################
+##
+#F FullRowSpace( , )
+##
+## <#GAPDoc Label="FullRowSpace">
+##
+##
+##
+##
+##
+## For a field F and a nonnegative integer n,
+## returns the F-vector space that
+## consists of all row vectors (see ) of
+## length n with entries in F.
+##
+## An alternative to construct this vector space is via
+## F^n.
+## FullRowSpace( GF( 9 ), 3 );
+## ( GF(3^2)^3 )
+## gap> GF(9)^3; # the same as above
+## ( GF(3^2)^3 )
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "FullRowSpace", FullRowModule );
+DeclareSynonym( "RowSpace", FullRowModule );
+
+
+#############################################################################
+##
+#F FullMatrixSpace( , , )
+##
+## <#GAPDoc Label="FullMatrixSpace">
+##
+##
+##
+##
+##
+## For a field F and two positive integers m and n,
+## returns the F-vector space that
+## consists of all m by n matrices
+## (see ) with entries in F.
+##
+## If m = n then the result is in fact an algebra
+## (see ).
+##
+## An alternative to construct this vector space is via
+## F^[m,n].
+## FullMatrixSpace( GF(2), 4, 5 );
+## ( GF(2)^[ 4, 5 ] )
+## gap> GF(2)^[ 4, 5 ]; # the same as above
+## ( GF(2)^[ 4, 5 ] )
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareSynonym( "FullMatrixSpace", FullMatrixModule );
+DeclareSynonym( "MatrixSpace", FullMatrixModule );
+DeclareSynonym( "MatSpace", FullMatrixModule );
+
+
+#############################################################################
+##
+#C IsSubspacesVectorSpace( )
+##
+## <#GAPDoc Label="IsSubspacesVectorSpace">
+##
+##
+##
+##
+## The domain of all subspaces of a (finite) vector space or of all
+## subspaces of fixed dimension, as returned by
+## (see ) lies in the category
+## .
+## D:= Subspaces( GF(3)^3 );
+## Subspaces( ( GF(3)^3 ) )
+## gap> Size( D );
+## 28
+## gap> iter:= Iterator( D );;
+## gap> NextIterator( iter );
+##
+## gap> NextIterator( iter );
+##
+## gap> IsSubspacesVectorSpace( D );
+## true
+## ]]>
+##
+##
+## <#/GAPDoc>
+##
+DeclareCategory( "IsSubspacesVectorSpace", IsDomain );
+
+
+#############################################################################
+##
+#M IsFinite( ) . . . . . . . . . . . . . . . . . for a subspaces domain
+##
+## Returns `true' if is finite.
+## We allow subspaces domains in `IsSubspacesVectorSpace' only for finite
+## vector spaces.
+##
+InstallTrueMethod( IsFinite, IsSubspacesVectorSpace );
+
+
+#############################################################################
+##
+#A Subspaces( [, ] )
+##
+## <#GAPDoc Label="Subspaces">
+##
+##
+##
+##
+## Called with a finite vector space v,
+## returns the domain of all subspaces of V.
+##
+## Called with V and a nonnegative integer k,
+## returns the domain of all k-dimensional
+## subspaces of V.
+##
+## Special and methods are
+## provided for these domains.
+##
+##
+##
+## <#/GAPDoc>
+##
+DeclareAttribute( "Subspaces", IsLeftModule );
+DeclareOperation( "Subspaces", [ IsLeftModule, IsInt ] );
+
+
+#############################################################################
+##
+#F IsSubspace( , )
+##
+##
+##
+##
+##
+## check that U is a vector space that is contained in V
+##
+##
+##
+##
+DeclareGlobalFunction( "IsSubspace" );
+
+
+#############################################################################
+##
+#A OrthogonalSpaceInFullRowSpace( )
+##
+##
+##
+##
+##
+## For a Gaussian row space U over F,
+##
+## returns a complement of U in the full row space of same vector
+## dimension as U over F.
+##
+##
+##
+DeclareAttribute( "OrthogonalSpaceInFullRowSpace", IsGaussianSpace );
+
+
+#############################################################################
+##
+#P IsVectorSpaceHomomorphism(