#############################################################################
##
#W GAPDoc2LaTeX.gi GAPDoc Frank Lübeck
##
##
#Y Copyright (C) 2000, Frank Lübeck, Lehrstuhl D für Mathematik,
#Y RWTH Aachen
##
## The files GAPDoc2LaTeX.g{d,i} contain a conversion program which
## produces from a GAPDoc XML-document a version which can be processed
## by LaTeX and pdfLaTeX.
##
## All the work is done by handler functions for each GAPDoc XML
## element. These functions are bound as components to the record
## `GAPDoc2LaTeXProcs'. Most element markup is easily translated to a
## corresponding LaTeX markup. It should be easy to modify details for
## some elements by small local changes of the corresponding handler
## function. The only slight complications are in places where the XML
## elements imply some labeling or indexing. Also for all (sub)section
## commands we add some commands which cause LaTeX to produce a
## GAP readable .pnr file which contains the page numbers for all
## subsections.
InstallValue(GAPDoc2LaTeXProcs, rec());
## <#GAPDoc Label="GAPDoc2LaTeX">
## <ManSection >
## <Func Arg="tree" Name="GAPDoc2LaTeX" />
## <Returns>&LaTeX; document as string</Returns>
## <Func Name="SetGapDocLaTeXOptions" Arg="[...]" />
## <Returns>Nothing</Returns>
## <Description>
## The argument <A>tree</A> for this function is a tree
## describing a &GAPDoc; XML document as returned by <Ref
## Func="ParseTreeXMLString" /> (probably also checked with <Ref
## Func="CheckAndCleanGapDocTree" />). The output is a string
## containing a version of the document which can be written to a
## file and processed with &LaTeX; or pdf&LaTeX; (and probably
## &BibTeX; and <C>makeindex</C>). <P/>
##
## The output uses the <C>report</C> document class and
## needs the following &LaTeX; packages:
## <C>amssymb</C>, <C>inputenc</C>, <C>makeidx</C>, <C>color</C>,
## <C>fancyvrb</C>, <C>psnfss</C>, <C>pslatex</C>, <C>enumitem</C>
## and <C>hyperref</C>. These are for example provided by the
## <Package>texlive</Package> distribution of &TeX; (which in turn
## is used for most &TeX; packages of current Linux distributions);
## see <URL>https://www.tug.org/texlive/</URL>. <P/>
##
## In particular, the resulting <C>pdf</C>-output (and
## <C>dvi</C>-output)
## contains (internal and external) hyperlinks which can be very
## useful for onscreen browsing of the document.<P/>
##
## The &LaTeX; processing also produces a file with extension
## <C>.pnr</C> which is &GAP; readable and contains the page numbers
## for all (sub)sections of the document. This can be used by
## &GAP;'s online help; see <Ref Func="AddPageNumbersToSix" />.
##
## Non-ASCII characters in the &GAPDoc; document are translated to
## &LaTeX; input in ASCII-encoding with the help of <Ref Oper="Encode"/>
## and the option <C>"LaTeX"</C>. See the documentation of
## <Ref Oper="Encode"/> for how to proceed if you have a character which
## is not handled (yet).<P/>
##
## This function works by running recursively through the document
## tree and calling a handler function for each &GAPDoc;
## XML element. Many of these handler functions (usually in
## <C>GAPDoc2LaTeXProcs.<ElementName></C>) are not difficult to
## understand (the greatest complications are some commands for index
## entries, labels or the output of page number information). So it
## should be easy to adjust layout details to your own taste by slight
## modifications of the program. <P/>
##
## Former versions of &GAPDoc; supported some XML processing
## instructions to add some extra lines to the preamble of the &LaTeX;
## document. Its use is now deprecated, use the much more flexible <Ref
## Func="SetGapDocLaTeXOptions" /> instead:
##
## The default layout of the resulting documents can
## be changed with <Ref Func="SetGapDocLaTeXOptions"/>. This
## changes parts of the header of the &LaTeX; file
## produced by &GAPDoc;. You can see the header with
## some placeholders by <C>Page(GAPDoc2LaTeXProcs.Head);</C>. The
## placeholders are filled with components from the record
## <C>GAPDoc2LaTeXProcs.DefaultOptions</C>. The arguments of <Ref
## Func="SetGapDocLaTeXOptions"/> can be records with the same
## structure (or parts of it) with different values. As abbreviations
## there are also three strings supported as arguments. These
## are <C>"nocolor"</C> for switching all colors to black; then
## <C>"nopslatex"</C> to use standard &LaTeX; fonts instead of
## postscript fonts; and finally <C>"utf8"</C> to choose UTF-8 as input
## encoding for the &LaTeX; document.
##
## </Description>
## </ManSection>
## <#/GAPDoc>
##
## <!-- seems to be no longer needed
## A hint for large documents: In many &TeX; installations one can
## easily reach some memory limitations with documents which contain
## many (cross-)references. In <Package>teTeX</Package> you can look
## for a file <F>texmf.cnf</F> which allows to enlarge certain
## memory sizes.<P/>
## -->
# the basic call, used recursivly with a result r from GetElement
# and a string str to which the output should be appended
# arg: r (then a string is returned)
# or: r, str (then the output is appended to string str)
InstallGlobalFunction(GAPDoc2LaTeX,
function(arg)
local r, str, name;
r := arg[
1];
if Length(arg)>
1 then
str := arg[
2];
else
AddRootParseTree(r);
# reset to defaults in case of interrupted previous call
GAPDoc2LaTeXProcs.verbatimPCDATA := false;
GAPDoc2LaTeXProcs.recode := true;
str :=
"";
fi;
name := r.name;
if not IsBound(GAPDoc2LaTeXProcs.(name))
then
Info(InfoGAPDoc,
1,
"#W WARNING: Don't know how to process element ", name,
" ---- ignored\n");
else
GAPDoc2LaTeXProcs.(r.name)(r, str);
fi;
if Length(arg)=
1 then
return str;
fi;
end);
## a common recursion loop
BindGlobal(
"GAPDoc2LaTeXContent",
function(r, str)
local a;
for a in r.content
do
GAPDoc2LaTeX(a, str);
od;
end);
# width of index entries, we use a trick to split longer command names
GAPDoc2LaTeXProcs.MaxIndexEntryWidth :=
35;
# a flag for recoding to LaTeX
GAPDoc2LaTeXProcs.recode := true;
# two utilities for attribute values like labels or text with special
# XML or LaTeX characters which gets printed (always as \texttt text)
GAPDoc2LaTeXProcs.EscapeAttrValOld :=
function(str)
local res, c;
res :=
"";
for c in str
do
if c =
'\\' then
## Append(res, "{\\gdttbs}");
Append(res,
"\\texttt{\\symbol{92}}");
elif c =
'_' then
Append(res,
"\\_");
elif c =
'{' then
## Append(res, "{\\gdttob}");
Append(res,
"\\texttt{\\symbol{123}}");
elif c =
'}' then
## Append(res, "{\\gdttcb}");
Append(res,
"\\texttt{\\symbol{125}}");
elif c =
'^' then
## Append(res, "{\\gdttht}");
Append(res,
"\\texttt{\\symbol{94}}");
elif c =
'~' then
## Append(res, "{\\gdttti}");
Append(res,
"\\texttt{\\symbol{126}}");
elif c =
'<' then
Append(res,
"{\\textless}");
elif c =
'>' then
Append(res,
"{\\textgreater}");
elif c =
'&' then
Append(res,
"\\&");
elif c =
'%' then
Append(res,
"\\%");
elif c =
'$' then
Append(res,
"\\$");
elif c =
'#' then
Append(res,
"\\#");
else
Add(res, c);
fi;
od;
return res;
end;
# now via Unicode, handle many more characters as well
GAPDoc2LaTeXProcs.EscapeAttrVal :=
function(str)
return Encode(Unicode(str), GAPDoc2LaTeXProcs.Encoder);
end;
GAPDoc2LaTeXProcs.DeleteUsBs :=
function(str)
local res, c;
if ForAny(str, c-> c in
"\\_")
then
res :=
"";
for c in str
do
if c =
'\\' then
Append(res,
"bSlash");
elif c =
'_' then
Append(res,
"uScore");
else
Add(res, c);
fi;
od;
return res;
fi;
return str;
end;
## this is for getting a string "[ \"A\", 1, 1 ]" from [ "A", 1, 1 ]
GAPDoc2LaTeXProcs.StringNrs :=
function(ssnr)
if IsInt(ssnr[
1])
then
return String(ssnr);
else
return Concatenation(
"[ \"", ssnr[1], "\
", ", String(ssnr[
2]),
", ",
String(ssnr[
3]),
" ]");
fi;
end;
GAPDoc2LaTeXProcs.Head := StringFile(
Filename(DirectoriesPackageLibrary(
"gapdoc"),
"latexhead.tex"));
GAPDoc2LaTeXProcs.Tail := Concatenation(
"\\newpage\n",
"\\immediate\\write\\pagenrlog{[\"End\
"], \\arabic{page}];}\n",
"\\immediate\\closeout\\pagenrlog\n",
"\\end{document}\n");
GAPDoc2LaTeXProcs.Options := rec();
GAPDoc2LaTeXProcs.DefaultOptions := rec(
EarlyExtraPreamble :=
"",
LateExtraPreamble :=
"",
InputEncoding :=
"latin1",
ColorDefinitions := rec(
link :=
"0.0,0.0,0.554",
cite :=
"0.0,0.0,0.554",
file :=
"0.0,0.0,0.554",
url :=
"0.0,0.0,0.554",
prompt :=
"0.0,0.0,0.589",
brkprompt :=
"0.589,0.0,0.0",
gapinput :=
"0.589,0.0,0.0",
gapoutput :=
"0.0,0.0,0.0",
funcdefs :=
"0.0,0.0,0.0",
chapter :=
"0.0,0.0,0.0"
),
MoreColors :=
"\\definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064}\n",
FontPackages :=
"\\usepackage{mathptmx,helvet}\n\\usepackage[T1]{fontenc}\n\
\\usepackage{textcomp}\n
",
HyperrefOptions := rec(
pdftex :=
"true",
bookmarks :=
"true",
a4paper :=
"true",
pdftitle :=
"{Written with GAPDoc}",
pdfcreator :=
"{LaTeX with hyperref package / GAPDoc}",
colorlinks :=
"true",
backref :=
"page",
breaklinks :=
"true",
pdfpagemode :=
"{UseNone}",
MoreHyperrefOptions :=
""
),
TocDepth :=
"\\setcounter{tocdepth}{1}",
Maintitlesize :=
"\\fontsize{50}{55}\\selectfont",
);
# helper function to apply the options to the generic LaTeX head
GAPDoc2LaTeXProcs.HeadWithOptions :=
function(extra)
local head, opt, f, ff;
head := GAPDoc2LaTeXProcs.Head;
opt := GAPDoc2LaTeXProcs.Options;
for f in RecNames(opt)
do
if f =
"ColorDefinitions" then
for ff in RecNames(opt.(f))
do
head := SubstitutionSublist(head,
Concatenation(
"CONFIGCOLOR",ff), opt.(f).(ff));
od;
elif f =
"HyperrefOptions" then
for ff in RecNames(opt.(f))
do
head := SubstitutionSublist(head,
Concatenation(
"CONFIGHR",ff), opt.(f).(ff));
od;
else
head := SubstitutionSublist(head,
Concatenation(
"CONFIG", f), opt.(f));
fi;
od;
head := SubstitutionSublist(head,
"PIExtraPreamble", extra);
return head;
end;
## arg: a list of strings
## for now only the output type (one of "dvi", "pdf" or "ps") is used
# to be enhanced
SetGapDocLaTeXOptions :=
function(arg)
local new, recs, r, f, ff;
GAPDoc2LaTeXProcs.Options := StructuralCopy(GAPDoc2LaTeXProcs.DefaultOptions);
new := GAPDoc2LaTeXProcs.Options;
recs := Filtered(arg, IsRecord);
# handle some abbreviations
if "nocolor" in arg
then
Add(recs, rec(
ColorDefinitions := rec(
link :=
"0.0,0.0,0.0",
cite :=
"0.0,0.0,0.0",
file :=
"0.0,0.0,0.0",
url :=
"0.0,0.0,0.0",
prompt :=
"0.0,0.0,0.0",
brkprompt :=
"0.0,0.0,0.0",
gapinput :=
"0.0,0.0,0.0",
gapoutput :=
"0.0,0.0,0.0",
funcdefs :=
"0.0,0.0,0.0",
chapter :=
"0.0,0.0,0.0"
) ) );
fi;
if "utf8" in arg
then
Add(recs, rec(InputEncoding :=
"utf8"));
fi;
if "nopslatex" in arg
then
Add(recs, rec(FontPackages :=
"\n"));
fi;
# now overwrite the defaults
for r in recs
do
for f in RecNames(r)
do
if IsRecord(r.(f))
then
if IsBound(new.(f))
then
for ff in RecNames(r.(f))
do
if IsBound(new.(f).(ff))
then
new.(f).(ff) := r.(f).(ff);
fi;
od;
fi;
else
if IsBound(new.(f))
then
new.(f) := r.(f);
fi;
fi;
od;
od;
# set encoder accordingly
if new.InputEncoding =
"utf8" then
GAPDoc2LaTeXProcs.Encoder :=
"LaTeXUTF8";
else
GAPDoc2LaTeXProcs.Encoder :=
"LaTeX";
fi;
end;
# set defaults
SetGapDocLaTeXOptions();
GAPDoc2LaTeXProcs.firstsix :=
function(r, count)
local a;
a := PositionSet(r.root.sixcount, count{[
1..
3]});
if a <> fail
then
a := r.root.six[r.root.sixindex[a]];
fi;
return a;
end;
## write head and foot of LaTeX file.
GAPDoc2LaTeXProcs.WHOLEDOCUMENT :=
function(r, str)
local i, pi, t, el, a;
## add internal paragraph numbering
AddParagraphNumbersGapDocTree(r);
## checking for processing instructions
i :=
1;
pi := rec();
while not r.content[i].name =
"Book" do
if r.content[i].name =
"XMLPI" then
t := r.content[i].content;
if Length(t) >
5 and t{[
1..
6]} =
"LaTeX " then
el := GetSTag(Concatenation(
"<", t,
">"),
2);
for a in NamesOfComponents(el.attributes)
do
pi.(a) := el.attributes.(a);
od;
fi;
fi;
i := i+
1;
od;
## collect headings of labeled sections, here we must run through the
## whole parse tree first to know the headings of text style forward
## references
GAPDoc2LaTeXProcs._labeledSections := rec();
r.root.norecursion := true;
ApplyToNodesParseTree(r,
function(rr)
if IsRecord(rr) and IsBound(rr.name)
and rr.name in [
"Chapter",
"Section",
"Subsection",
"Appendix"]
then
# save heading for "Text" style references to section
GAPDoc2LaTeXProcs.(rr.name)(rr,
"");
fi;
end);
Unbind(r.root.norecursion);
## warn if no labels via .six available
if not IsBound(r.six)
then
Info(InfoGAPDoc,
1,
"#W WARNING: No labels for section number independent ",
"anchors available.\n",
"#W Consider running the converter for the text version first!\n");
fi;
## now the actual work starts, we give the found processing instructions
## to the Book handler
GAPDoc2LaTeXProcs.Book(r.content[i], str, pi);
Unbind(GAPDoc2LaTeXProcs._labeledSections);
end;
## comments and processing instructions are generally ignored
GAPDoc2LaTeXProcs.XMLPI :=
function(r, str);
end;
GAPDoc2LaTeXProcs.XMLCOMMENT :=
function(r, str);
end;
# do nothing with Ignore
GAPDoc2LaTeXProcs.Ignore :=
function(arg)
end;
## this makes head and foot of the LaTeX output
## - the only processing instructions handled currently are
## - options for the report class (german, papersize, ...) and
## - extra entries in the preamble (\usepackage, macro definitions, ...)
GAPDoc2LaTeXProcs.Book :=
function(r, str, pi)
local a;
if not IsBound(pi.ExtraPreamble)
then
pi.ExtraPreamble :=
"";
fi;
Append(str, GAPDoc2LaTeXProcs.HeadWithOptions(pi.ExtraPreamble));
# and now the text of the document
GAPDoc2LaTeXContent(r, str);
# that's it
Append(str, GAPDoc2LaTeXProcs.Tail);
end;
## the Body just prints its content
GAPDoc2LaTeXProcs.Body := GAPDoc2LaTeXContent;
## the title page, the most complicated looking function
GAPDoc2LaTeXProcs.TitlePage :=
function(r, str)
local l, ll, a, s, cont;
# page number info for online help
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(r.count{[
1..
3]}),
"}\n"));
Append(str,
"\\begin{titlepage}\n\\mbox{}\\vfill\n\n\\begin{center}");
# title
l := Filtered(r.content, a-> a.name =
"Title");
Append(str,
"{\\maintitlesize \\textbf{");
s :=
"";
GAPDoc2LaTeXContent(l[
1], s);
Append(str, s);
Append(str,
"\\mbox{}}}\\\\\n\\vfill\n\n");
# set title in info part of PDF document
Append(str,
"\\hypersetup{pdftitle=");
Append(str, s);
Append(str,
"}\n");
# the title is also used for the page headings
Append(str,
"\\markright{\\scriptsize \\mbox{}\\hfill ");
Append(str, s);
Append(str,
" \\hfill\\mbox{}}\n");
# subtitle
l := Filtered(r.content, a-> a.name =
"Subtitle");
if Length(l)>
0 then
Append(str,
"{\\Huge \\textbf{");
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}}\\\\\n\\vfill\n\n");
fi;
# version
l := Filtered(r.content, a-> a.name =
"Version");
if Length(l)>
0 then
Append(str,
"{\\Huge ");
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}\\\\[1cm]\n");
fi;
# date
l := Filtered(r.content, a-> a.name =
"Date");
if Length(l)>
0 then
Append(str,
"{");
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}\\\\[1cm]\n");
fi;
Append(str,
"\\mbox{}\\\\[2cm]\n");
# author name(s)
l := Filtered(r.content, a-> a.name =
"Author");
# collect author list for PDF info
ll := [];
for a in l
do
Append(str,
"{\\Large \\textbf{");
s :=
"";
GAPDoc2LaTeXContent(rec(content := Filtered(a.content, b->
not b.name in [
"Email",
"Homepage",
"Address"])), s);
Append(str, s);
Add(ll, s);
Append(str,
"\\mbox{}}}\\\\\n");
od;
Append(str,
"\\hypersetup{pdfauthor=");
Append(str, JoinStringsWithSeparator(ll,
"; "));
Append(str,
"}\n");
# extra comment for front page
l := Filtered(r.content, a-> a.name =
"TitleComment");
if Length(l) >
0 then
Append(str,
"\\mbox{}\\\\[2cm]\n\\begin{minipage}{12cm}\\noindent\n");
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\end{minipage}\n\n");
fi;
Append(str,
"\\end{center}\\vfill\n\n\\mbox{}\\\\\n");
# email, WWW-homepage and address of author(s), if given
l := Filtered(r.content, a-> a.name =
"Author");
for a in l
do
cont := List(a.content, b-> b.name);
if "Email" in cont or
"Homepage" in cont or
"Address" in cont
then
Append(str,
"{\\mbox{}\\\\\n\\small \\noindent \\textbf{");
GAPDoc2LaTeXContent(rec(content := Filtered(a.content, b->
not b.name in [
"Email",
"Homepage",
"Address"])), str);
Append(str,
"}");
if "Email" in cont
then
Append(str, Concatenation(
" ", GAPDocTexts.d.Email,
": "));
GAPDoc2LaTeX(a.content[Position(cont,
"Email")], str);
fi;
if "Homepage" in cont
then
Append(str,
"\\\\\n");
Append(str, Concatenation(
" ", GAPDocTexts.d.Homepage,
": "));
GAPDoc2LaTeX(a.content[Position(cont,
"Homepage")], str);
fi;
if "Address" in cont
then
Append(str,
"\\\\\n");
Append(str, Concatenation(
" ", GAPDocTexts.d.Address,
": \\begin{minipage}[t]{8cm}\\noindent\n"));
GAPDoc2LaTeX(a.content[Position(cont,
"Address")], str);
Append(str,
"\\end{minipage}\n");
fi;
Append(str,
"}\\\\\n");
fi;
od;
# Address outside the Author elements
l := Filtered(r.content, a-> a.name =
"Address");
if Length(l)>
0 then
Append(str,
"\n\\noindent ");
Append(str, Concatenation(
"\\textbf{", GAPDocTexts.d.Address,
": }\\begin{minipage}[t]{8cm}\\noindent\n"));
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\end{minipage}\n");
fi;
Append(str,
"\\end{titlepage}\n\n\\newpage");
# to make physical page numbers same as document page numbers
Append(str,
"\\setcounter{page}{2}\n");
# abstract
l := Filtered(r.content, a-> a.name =
"Abstract");
if Length(l)>
0 then
Append(str, Concatenation(
"{\\small \n\\section*{", GAPDocTexts.d.Abstract,
"}\n"));
# page number info for online help
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(l[
1].count{[
1..
3]}),
"}\n"));
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}\\\\[1cm]\n");
fi;
# copyright page
l := Filtered(r.content, a-> a.name =
"Copyright");
if Length(l)>
0 then
Append(str, Concatenation(
"{\\small \n\\section*{", GAPDocTexts.d.Copyright,
"}\n"));
# page number info for online help
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(l[
1].count{[
1..
3]}),
"}\n"));
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}\\\\[1cm]\n");
fi;
# acknowledgement page
l := Filtered(r.content, a-> a.name =
"Acknowledgements");
if Length(l)>
0 then
Append(str, Concatenation(
"{\\small \n\\section*{",
GAPDocTexts.d.Acknowledgements,
"}\n"));
# page number info for online help
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(l[
1].count{[
1..
3]}),
"}\n"));
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}\\\\[1cm]\n");
fi;
# colophon page
l := Filtered(r.content, a-> a.name =
"Colophon");
if Length(l)>
0 then
Append(str, Concatenation(
"{\\small \n\\section*{", GAPDocTexts.d.Colophon,
"}\n"));
# page number info for online help
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(l[
1].count{[
1..
3]}),
"}\n"));
GAPDoc2LaTeXContent(l[
1], str);
Append(str,
"\\mbox{}}\\\\[1cm]\n");
fi;
Append(str,
"\\newpage\n\n");
end;
## this allows line breaks in URL strings s for use with \texttt{s} by
## inserting some "}\discretionary{}{}{}\texttt{"
GAPDoc2LaTeXProcs.URLBreaks :=
function(s)
local pos, ss, old;
# not after ://
pos := PositionSublist(s,
"://");
if pos = fail
then
pos := Minimum(
3, Length(s));
else
pos := pos +
2;
fi;
ss := s{[
1..pos]};
old := pos;
pos := Position(s,
'/', old);
while pos <> fail and pos+
3 < Length(s)
do
Append(ss, s{[old+
1..pos]});
Append(ss,
"}\\discretionary {}{}{}\\texttt{");
old := pos;
pos := Position(s,
'/', old);
od;
Append(ss, s{[old+
1..Length(s)]});
return ss;
end;
## ~ and # characters are correctly escaped
## arg: r, str[, pre]
GAPDoc2LaTeXProcs.Link := GAPDoc2LaTeXContent;
GAPDoc2LaTeXProcs.LinkText := GAPDoc2LaTeXContent;
GAPDoc2LaTeXProcs.URL :=
function(arg)
local r, str, pre, rr, txt, s;
r := arg[
1];
str := arg[
2];
if Length(arg)>
2 then
pre := arg[
3];
else
pre :=
"";
fi;
rr := First(r.content, a-> a.name =
"LinkText");
if rr <> fail
then
txt :=
"";
GAPDoc2LaTeXContent(rr, txt);
rr := First(r.content, a-> a.name =
"Link");
if rr = fail
then
Info(InfoGAPDoc,
1,
"#W missing <Link> element for text ", txt, "\n");
s :=
"MISSINGLINK";
else
s :=
"";
# must avoid recoding for first argument of \href
GAPDoc2LaTeXProcs.recode := false;
GAPDoc2LaTeXContent(rr, s);
GAPDoc2LaTeXProcs.recode := true;
fi;
else
s :=
"";
GAPDoc2LaTeXProcs.recode := false;
GAPDoc2LaTeXContent(r, s);
GAPDoc2LaTeXProcs.recode := true;
if IsBound(r.attributes.Text)
then
txt := r.attributes.Text;
else
# need recode in second argument of \href
txt := Encode(Unicode(s,
"UTF-8"), GAPDoc2LaTeXProcs.Encoder);
txt := Concatenation(
"\\texttt{", txt,
"}");
fi;
fi;
Append(str, Concatenation(
"\\href{", pre, s,
"} {", txt,
"}"));
end;
GAPDoc2LaTeXProcs.Homepage := GAPDoc2LaTeXProcs.URL;
GAPDoc2LaTeXProcs.Email :=
function(r, str)
# we add the `mailto://' phrase
GAPDoc2LaTeXProcs.URL(r, str,
"mailto://");
end;
## the sectioning commands are just translated and labels are
## generated, if given as attribute
GAPDoc2LaTeXProcs.ChapSect :=
function(r, str, sect)
local posh, a, s;
posh := Position(List(r.content, a-> a.name),
"Heading");
# heading
Append(str, Concatenation(
"\n\\", sect,
"{"));
s :=
"";
if posh <> fail
then
GAPDoc2LaTeXProcs.Heading1(r.content[posh], s);
fi;
Append(str,
"\\textcolor{Chapter }{");
Append(str, s);
Append(str,
"}}");
# label for references
if IsBound(r.attributes.Label)
then
Append(str,
"\\label{");
Append(str, r.attributes.Label);
Append(str,
"}\n");
# save heading for "Text" style references to section
GAPDoc2LaTeXProcs._labeledSections.(r.attributes.Label) := s;
fi;
# page number info for online help (no r.count below Ignore),
# we also add a section number and page number independent label,
# if available
if IsBound(r.count)
then
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(r.count{[
1..
3]}),
"}\n"));
if IsBound(r.root.six)
then
## a := First(r.root.six, x-> x[3] = r.count{[1..3]});
a := GAPDoc2LaTeXProcs.firstsix(r, r.count);
if a <> fail and IsBound(a[
7])
then
Append(str, Concatenation(
"\\hyperdef{L}{", a[
7],
"}{}\n"));
fi;
fi;
# the actual content
if not IsBound(r.root.norecursion)
then
Append(str,
"{\n");
GAPDoc2LaTeXContent(r, str);
Append(str,
"}\n\n");
fi;
fi;
end;
## this really produces the content of the heading
GAPDoc2LaTeXProcs.Heading1 :=
function(r, str)
GAPDoc2LaTeXContent(r, str);
end;
## and this ignores the heading (for simpler recursion)
GAPDoc2LaTeXProcs.Heading :=
function(r, str)
end;
GAPDoc2LaTeXProcs.Chapter :=
function(r, str)
GAPDoc2LaTeXProcs.ChapSect(r, str,
"chapter");
end;
GAPDoc2LaTeXProcs.Appendix :=
function(r, str)
if r.count[
1] =
"A" then
Append(str,
"\n\n\\appendix\n\n");
fi;
GAPDoc2LaTeXProcs.ChapSect(r, str,
"chapter");
end;
GAPDoc2LaTeXProcs.Section :=
function(r, str)
GAPDoc2LaTeXProcs.ChapSect(r, str,
"section");
end;
GAPDoc2LaTeXProcs.Subsection :=
function(r, str)
GAPDoc2LaTeXProcs.ChapSect(r, str,
"subsection");
end;
## table of contents, the job is completely delegated to LaTeX
GAPDoc2LaTeXProcs.TableOfContents :=
function(r, str)
# page number info for online help
Append(str, Concatenation(
"\\def\\contentsname{", GAPDocTexts.d.Contents,
"\\logpage{", GAPDoc2LaTeXProcs.StringNrs(r.count{[
1..
3]}),
"}}\n"));
Append(str,
"\n\\tableofcontents\n\\newpage\n\n");
end;
## bibliography, the job is completely delegated to LaTeX and BibTeX
GAPDoc2LaTeXProcs.Bibliography :=
function(r, str)
local dat, fname, t, b, st, a;
# check if bib data are in BibXMLext format, in that case produce a
# BibTeX file
dat := r.attributes.Databases;
dat := SplitString(dat,
"",
", \n\t\b");
dat := Filtered(dat, a-> Length(a) >
3 and
a{[Length(a)-
3..Length(a)]} =
".xml");
dat := List(dat, a-> Filename(r.root.bibpath, a));
for fname in dat
do
b := ParseBibXMLextFiles(fname);
b := List(b.entries, a-> RecBibXMLEntry(a, b.strings,
"BibTeX"));
WriteBibFile(Concatenation(fname,
".bib"), [b, [], []]);
od;
if IsBound(r.attributes.Style)
then
st := r.attributes.Style;
else
st :=
"alpha";
fi;
# page number info for online help
Append(str, Concatenation(
"\\def\\bibname{", GAPDocTexts.d.References,
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(r.count{[
1..
3]}),
"}\n"));
if IsBound(r.root.six)
then
## a := First(r.root.six, x-> x[3] = r.count{[1..3]});
a := GAPDoc2LaTeXProcs.firstsix(r, r.count);
if a <> fail and IsBound(a[
7])
then
Append(str, Concatenation(
"\\hyperdef{L}{", a[
7],
"}{}\n"));
fi;
fi;
Append(str,
"}\n");
Append(str,
"\n\\bibliographystyle{");
Append(str, st);
Append(str,
"}\n\\bibliography{");
Append(str, r.attributes.Databases);
Append(str,
"}\n\n");
# toc entry
Append(str,
"\\addcontentsline{toc}{chapter}{");
Append(str, GAPDocTexts.d.References);
Append(str,
"}\n\n");
end;
## as default we normalize white space in text and split the result
## into lines (leading and trailing white space is also substituted
## by one space).
GAPDoc2LaTeXProcs.PCDATA :=
function(r, str)
local lines, i;
if GAPDoc2LaTeXProcs.verbatimPCDATA
then
# no reformatting at all, used for <Alt Only="LaTeX"> content
Append(str, r.content);
return;
fi;
if Length(r.content)>
0 and r.content[
1] in WHITESPACE
then
Add(str,
' ');
fi;
lines := r.content;
if GAPDoc2LaTeXProcs.recode = true
then
lines := Encode(Unicode(lines), GAPDoc2LaTeXProcs.Encoder);
fi;
lines := FormatParagraph(lines,
"left");
if Length(lines)>
0 then
if r.content[Length(r.content)] in WHITESPACE
then
lines[Length(lines)] :=
' ';
else
Unbind(lines[Length(lines)]);
fi;
fi;
Append(str, lines);
end;
## end of paragraph
GAPDoc2LaTeXProcs.P :=
function(r, str)
Append(str,
"\n\n");
end;
## forced line break
GAPDoc2LaTeXProcs.Br :=
function(r, str)
Append(str,
"\\\\\n");
end;
## generic function to get content and wrap by some markup
GAPDoc2LaTeXProcs.WrapMarkup :=
function(r, str, pre, post)
local s;
s :=
"";
GAPDoc2LaTeXContent(r, s);
Append(str, Concatenation(pre, s, post));
end;
## setting in typewriter
GAPDoc2LaTeXProcs.WrapTT :=
function(r, str)
GAPDoc2LaTeXProcs.WrapMarkup(r, str,
"\\texttt{",
"}");
end;
## GAP keywords
GAPDoc2LaTeXProcs.K :=
function(r, str)
GAPDoc2LaTeXProcs.WrapTT(r, str);
end;
## verbatim GAP code
GAPDoc2LaTeXProcs.C :=
function(r, str)
GAPDoc2LaTeXProcs.WrapTT(r, str);
end;
## file names
GAPDoc2LaTeXProcs.F :=
function(r, str)
GAPDoc2LaTeXProcs.WrapTT(r, str);
end;
## argument names
GAPDoc2LaTeXProcs.A :=
function(r, str)
Append(str,
"\\mbox{");
## GAPDoc2LaTeXProcs.WrapTT(r, str);
## the \mdseries is necessary because there is no bold-sl which
## LaTeX substitutes by bold-normal, but we want medium-sl
GAPDoc2LaTeXProcs.WrapMarkup(r, str,
"\\texttt{\\mdseries\\slshape ",
"}");
Append(str,
"}");
end;
## simple maths
GAPDoc2LaTeXProcs.M :=
function(r, str)
local saveenc;
Append(str,
"$");
# here the input is already coded in LaTeX
saveenc := GAPDoc2LaTeXProcs.Encoder;
GAPDoc2LaTeXProcs.Encoder :=
"LaTeXleavemarkup";
GAPDoc2LaTeXContent(r, str);
GAPDoc2LaTeXProcs.Encoder := saveenc;
Append(str,
"$");
end;
## in LaTeX same as <M>
GAPDoc2LaTeXProcs.Math := GAPDoc2LaTeXProcs.M;
## displayed maths
GAPDoc2LaTeXProcs.Display :=
function(r, str)
local saveenc;
if Length(str)>
0 and str[Length(str)] <>
'\n' then
Add(str,
'\n');
fi;
Append(str,
"\\[");
saveenc := GAPDoc2LaTeXProcs.Encoder;
GAPDoc2LaTeXProcs.Encoder :=
"LaTeXleavemarkup";
GAPDoc2LaTeXContent(r, str);
GAPDoc2LaTeXProcs.Encoder := saveenc;
Append(str,
"\\]\n");
end;
## emphazised text
GAPDoc2LaTeXProcs.Emph :=
function(r, str)
local a;
Append(str,
"\\emph{");
GAPDoc2LaTeXContent(r, str);
Append(str,
"}");
end;
## quoted text
GAPDoc2LaTeXProcs.Q :=
function(r, str)
local a;
Append(str,
"``");
GAPDoc2LaTeXContent(r, str);
Append(str,
"''");
end;
## Package names
GAPDoc2LaTeXProcs.Package :=
function(r, str)
local a;
Append(str,
"\\textsf{");
GAPDoc2LaTeXContent(r, str);
Append(str,
"}");
end;
## menu items
GAPDoc2LaTeXProcs.B :=
function(r, str)
local a;
Append(str,
"\\textsc{");
GAPDoc2LaTeXContent(r, str);
Append(str,
"}");
end;
GAPDoc2LaTeXProcs.verbcontent :=
function(r, delfirst)
local cont;
# here we cannot use recoding, fall back to SimplifiedUnicodeString (latin1)
# first collect content without recoding or reformatting
cont := GetTextXMLTree(r);
if GAPDoc2LaTeXProcs.Options.InputEncoding =
"latin1" then
cont := Encode(SimplifiedUnicodeString(Unicode(cont),
"latin1"),
"latin1");
fi;
cont := SplitString(cont,
"\n",
"");
# if first line has white space only, we remove it
if delfirst and Length(cont) >
0 and ForAll(cont[
1], x-> x in WHITESPACE)
then
cont := cont{[
2..Length(cont)]};
fi;
cont := Concatenation(List(cont, a-> Concatenation(
" ", a,
"\n")));
return cont;
end;
## verbatim GAP session
GAPDoc2LaTeXProcs.Verb :=
function(r, str)
local cont, a, s;
Append(str,
"\n\\begin{verbatim}");
Append(str, GAPDoc2LaTeXProcs.verbcontent(r, false));
Append(str,
"\\end{verbatim}\n");
end;
GAPDoc2LaTeXProcs.ExampleLike :=
function(r, str, label, findprompts)
local cont, comopt, comchars, sp, pos, c;
cont := GAPDoc2LaTeXProcs.verbcontent(r, true);
comopt :=
"";
if findprompts
then
comchars :=
"";
for c in Concatenation(
"!@|", LETTERS)
do
if not c in cont and
# avoid letters in used command names
not c in
"Vabdegikmnoprtu" then
Add(comchars, c);
if Length(comchars) =
3 then
break;
fi;
fi;
od;
if Length(comchars) =
3 then
comopt := Concatenation(
"commandchars=",comchars,
",");
sp := SplitString(cont,
"\n",
"");
cont :=
"";
for r in sp
do
if Length(r) >
6 and r{[
1..
7]} =
" gap> " then
Append(cont, Concatenation(
" ",comchars{[
1]},
"gapprompt",comchars{[
2]},
"gap>",comchars{[
3]},
" ",comchars{[
1]},
"gapinput",
comchars{[
2]},r{[
8..Length(r)]},comchars{[
3]},
"\n"));
elif Length(r) >
3 and r{[
1..
4]} =
" > " then
Append(cont, Concatenation(
" ",comchars{[
1]},
"gapprompt",comchars{[
2]},
">",comchars{[
3]},
" ",comchars{[
1]},
"gapinput",
comchars{[
2]},r{[
5..Length(r)]},comchars{[
3]},
"\n"));
elif Length(r) >
5 and r{[
1..
5]} =
" brk" then
pos := Position(r,
'>');
Append(cont, Concatenation(
" ",comchars{[
1]},
"gapbrkprompt",comchars{[
2]},
r{[
3..pos]},comchars{[
3]},
" ",comchars{[
1]},
"gapinput",
comchars{[
2]},r{[pos+
2..Length(r)]},comchars{[
3]},
"\n"));
else
Append(cont, r);
Add(cont,
'\n');
fi;
od;
fi;
fi;
Append(str, Concatenation(
"\n\\begin{Verbatim}[",comopt,
"fontsize=\\small,",
"frame=single,label=", label,
"]\n"));
Append(str, cont);
Append(str,
"\\end{Verbatim}\n");
end;
## log of session and GAP code is typeset the same way as <Example>
GAPDoc2LaTeXProcs.Example :=
function(r, str)
GAPDoc2LaTeXProcs.ExampleLike(r, str, GAPDocTexts.d.Example, true);
end;
GAPDoc2LaTeXProcs.Log :=
function(r, str)
GAPDoc2LaTeXProcs.ExampleLike(r, str, GAPDocTexts.d.Log, true);
end;
GAPDoc2LaTeXProcs.Listing :=
function(r, str)
if IsBound(r.attributes.Type)
then
GAPDoc2LaTeXProcs.ExampleLike(r, str, r.attributes.Type, true);
else
GAPDoc2LaTeXProcs.ExampleLike(r, str,
"", true);
fi;
end;
## explicit labels
GAPDoc2LaTeXProcs.Label :=
function(r, str)
Append(str,
"\\label{");
Append(str, r.attributes.Name);
Append(str,
"}");
end;
## citations
GAPDoc2LaTeXProcs.Cite :=
function(r, str)
Append(str,
"\\cite");
if IsBound(r.attributes.Where)
then
Add(str,
'[');
Append(str, Encode(Unicode(r.attributes.Where), GAPDoc2LaTeXProcs.Encoder));
Add(str,
']');
fi;
Add(str,
'{');
Append(str, r.attributes.Key);
Add(str,
'}');
end;
## explicit index entries
GAPDoc2LaTeXProcs.Subkey := GAPDoc2LaTeXContent;
## 'makeindex' has the following rule to include its special characters
GAPDoc2LaTeXProcs.EscapeIndexChars :=
function(str)
str := ReplacedString(str,
"\"", "\
"\"");
str := ReplacedString(str,
"@",
"\"@
");
str := ReplacedString(str,
"!",
"\"!
");
str := ReplacedString(str,
"|",
"\"|
");
return str;
end;
GAPDoc2LaTeXProcs.Index :=
function(r, str)
local s, sub, a, esc;
esc := GAPDoc2LaTeXProcs.EscapeIndexChars;
s :=
"";
sub :=
"";
for a in r.content
do
if a.name =
"Subkey" then
GAPDoc2LaTeX(a, sub);
else
GAPDoc2LaTeX(a, s);
fi;
od;
NormalizeWhitespace(s);
NormalizeWhitespace(sub);
if IsBound(r.attributes.Key)
then
s := Concatenation(esc(r.attributes.Key),
"@", esc(s));
fi;
if Length(sub) >
0 then
s := Concatenation(s,
"!", esc(sub));
elif IsBound(r.attributes.Subkey)
then
s := Concatenation(s,
"!", esc(r.attributes.Subkey));
fi;
Append(str,
"\\index{");
Append(str, s);
Append(str,
"}");
end;
## this produces an implicit index entry and a label entry
GAPDoc2LaTeXProcs.LikeFunc :=
function(r, str, typ)
local nam, namclean, lab, inam, i;
Append(str,
"\\noindent\\textcolor{FuncColor}{$\\triangleright$\\enspace\\texttt{");
nam := r.attributes.Name;
namclean := GAPDoc2LaTeXProcs.DeleteUsBs(nam);
# we allow _, \ and so on here
nam := GAPDoc2LaTeXProcs.EscapeAttrVal(nam);
Append(str, nam);
if IsBound(r.attributes.Arg)
then
Append(str,
"({\\mdseries\\slshape ");
Append(str, GAPDoc2LaTeXProcs.EscapeAttrVal(
NormalizedArgList(r.attributes.Arg)));
Append(str,
"})");
fi;
# possible label
if IsBound(r.attributes.Label)
then
lab := Concatenation(
"!", r.attributes.Label);
else
lab :=
"";
fi;
# index entry
# handle extremely long names
if Length(nam) > GAPDoc2LaTeXProcs.MaxIndexEntryWidth
then
inam := nam{[
1..
3]};
for i in [
4..Length(nam)-
3]
do
if nam[i] in CAPITALLETTERS
then
Append(inam,
"}\\-\\texttt{");
fi;
Add(inam, nam[i]);
od;
Add(inam, nam[Length(nam)-
2]); Add(inam, nam[Length(nam)-
1]);
Add(inam, nam[Length(nam)]);
else
inam := nam;
fi;
Append(str, Concatenation(
"\\index{",
GAPDoc2LaTeXProcs.EscapeIndexChars(nam),
"@\\texttt{",
inam,
"}", lab,
"}\n"));
# label (if not given, the default is the Name)
if IsBound(r.attributes.Label)
then
namclean := Concatenation(namclean,
":", r.attributes.Label);
fi;
Add(GAPDoc2LaTeXProcs._currentSubsection, namclean);
Append(str, Concatenation(
"\\label{", namclean,
"}\n"));
# some hint about the type of the variable
Append(str,
"}\\hfill{\\scriptsize (");
Append(str, typ);
Append(str,
")}}\\\\\n");
end;
GAPDoc2LaTeXProcs.Func :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Func);
end;
GAPDoc2LaTeXProcs.Oper :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Oper);
end;
GAPDoc2LaTeXProcs.Constr :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Constr);
end;
GAPDoc2LaTeXProcs.Meth :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Meth);
end;
GAPDoc2LaTeXProcs.Filt :=
function(r, str)
# r.attributes.Type could be "representation", "category", ...
if IsBound(r.attributes.Type)
then
GAPDoc2LaTeXProcs.LikeFunc(r, str, r.attributes.Type);
else
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Filt);
fi;
end;
GAPDoc2LaTeXProcs.Prop :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Prop);
end;
GAPDoc2LaTeXProcs.Attr :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Attr);
end;
GAPDoc2LaTeXProcs.Var :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Var);
end;
GAPDoc2LaTeXProcs.Fam :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.Fam);
end;
GAPDoc2LaTeXProcs.InfoClass :=
function(r, str)
GAPDoc2LaTeXProcs.LikeFunc(r, str, GAPDocTexts.d.InfoClass);
end;
## using the HelpData(.., .., "ref") interface
GAPDoc2LaTeXProcs.ResolveExternalRef :=
function(bookname, label, nr)
local info, match, res;
info := HELP_BOOK_INFO(bookname);
if info = fail
then
return fail;
fi;
match := Concatenation(HELP_GET_MATCHES(info, SIMPLE_STRING(label), true));
# maybe change, and check if there are matches to several subsections?
#ssecs := List(match, i-> HELP_BOOK_HANDLER.(info.handler).HelpData(info,
# match[i][2], "ref")[7]);
if Length(match) < nr
then
return fail;
fi;
res := GetHelpDataRef(info, match[nr][
2]);
res[
1] := SubstitutionSublist(res[
1],
" (not loaded): ",
": ",
"one");
return res;
end;
GAPDoc2LaTeXProcs.Ref :=
function(r, str)
local funclike, int, txt, ref, lab, sectlike, slab;
# function like cases
funclike := [
"Func",
"Oper",
"Constr",
"Meth",
"Filt",
"Prop",
"Attr",
"Var",
"Fam",
"InfoClass" ];
int := Intersection(funclike, NamesOfComponents(r.attributes));
if Length(int)>
0 then
txt := r.attributes.(int[
1]);
if IsBound(r.attributes.Label)
then
lab := Concatenation(txt,
":", r.attributes.Label);
else
lab := txt;
fi;
if IsBound(r.attributes.BookName)
then
slab := txt;
if IsBound(r.attributes.Label)
then
slab := Concatenation(slab,
" (", r.attributes.Label,
")");
fi;
ref := GAPDoc2LaTeXProcs.ResolveExternalRef(
r.attributes.BookName, slab,
1);
if ref = fail
then
Info(InfoGAPDoc,
1,
"#W WARNING: non resolved reference: ",
r.attributes,
"\n");
ref := Concatenation(
" (", Encode(Unicode(lab),
GAPDoc2LaTeXProcs.Encoder)
,
"???)");
else
# the search text for online help including book name
ref := Concatenation(
" (\\textbf{",
GAPDoc2LaTeXProcs.EscapeAttrVal(ref[
1]),
"})");
fi;
else
ref := Concatenation(
" (\\ref{", GAPDoc2LaTeXProcs.DeleteUsBs(lab),
"})");
fi;
# delete ref, if pointing to current subsection
if not IsBound(r.attributes.BookName) and
IsBound(GAPDoc2LaTeXProcs._currentSubsection) and
lab in GAPDoc2LaTeXProcs._currentSubsection
then
ref :=
"";
fi;
Append(str, Concatenation(
"\\texttt{", GAPDoc2LaTeXProcs.EscapeAttrVal(txt),
"}", ref));
return;
fi;
# section like cases
sectlike := [
"Chap",
"Sect",
"Subsect",
"Appendix"];
int := Intersection(sectlike, NamesOfComponents(r.attributes));
if Length(int)>
0 then
txt := r.attributes.(int[
1]);
if IsBound(r.attributes.Label)
then
lab := r.attributes.Label;
else
lab := txt;
fi;
if IsBound(r.attributes.BookName)
then
ref := GAPDoc2LaTeXProcs.ResolveExternalRef(
r.attributes.BookName, lab,
1);
if ref = fail
then
Info(InfoGAPDoc,
1,
"#W WARNING: non resolved reference: ",
r.attributes,
"\n");
ref := Concatenation(
" (", lab,
"???)");
else
# the search text for online help including book name
ref := Concatenation(
" (\\textbf{", GAPDoc2LaTeXProcs.EscapeAttrVal(ref[
1]),
"})");
fi;
elif IsBound(r.attributes.Style) and r.attributes.Style =
"Text" then
if IsBound(GAPDoc2LaTeXProcs._labeledSections.(lab))
then
ref := Concatenation(
"\\hyperref[",lab,
"]{`", StripBeginEnd(
GAPDoc2LaTeXProcs._labeledSections.(lab), WHITESPACE),
"'}");
else
Info(InfoGAPDoc,
1,
"#W WARNING: non resolved reference: ",
r.attributes,
"\n");
ref :=
"`???'";
fi;
else
# with sectioning references Label must be given
lab := r.attributes.(int[
1]);
#ref := Concatenation("\\ref{", GAPDoc2LaTeXProcs.EscapeAttrVal(lab), "}");
ref := Concatenation(
"\\ref{", lab,
"}");
fi;
Append(str, ref);
return;
fi;
# neutral reference to a label
if IsBound(r.attributes.BookName)
then
if IsBound(r.attributes.Label)
then
lab := r.attributes.Label;
else
lab :=
"_X_X_X";
fi;
ref := GAPDoc2LaTeXProcs.ResolveExternalRef(
r.attributes.BookName, lab,
1);
if ref = fail
then
Info(InfoGAPDoc,
1,
"#W WARNING: non resolved reference: ",
r.attributes,
"\n");
ref := Concatenation(
" ", GAPDoc2LaTeXProcs.EscapeAttrVal(lab),
"??? ");
else
# the search text for online help including book name
ref := Concatenation(
" \\textbf{", GAPDoc2LaTeXProcs.EscapeAttrVal(ref[
1]),
"}");
fi;
else
lab := r.attributes.Label;
ref := Concatenation(
"\\ref{", GAPDoc2LaTeXProcs.EscapeAttrVal(lab),
"}");
fi;
Append(str, ref);
return;
end;
# just process
GAPDoc2LaTeXProcs.Address :=
function(r, str)
GAPDoc2LaTeXContent(r, str);
end;
GAPDoc2LaTeXProcs.Description :=
function(r, str)
Append(str,
"\n\n");
GAPDoc2LaTeXContent(r, str);
end;
GAPDoc2LaTeXProcs.Returns :=
function(r, str)
Append(str, Concatenation(
"\\textbf{\\indent ", GAPDocTexts.d.Returns,
":\\ }\n"));
GAPDoc2LaTeXContent(r, str);
Append(str,
"\n\n");
end;
GAPDoc2LaTeXProcs.ManSection :=
function(r, str)
local funclike, f, lab, i, a;
# if there is a Heading then handle as subsection
if ForAny(r.content, a-> IsRecord(a) and a.name =
"Heading")
then
GAPDoc2LaTeXProcs._currentSubsection := r.count{[
1..
3]};
GAPDoc2LaTeXProcs.ChapSect(r, str,
"subsection");
Unbind(GAPDoc2LaTeXProcs._currentSubsection);
return;
fi;
# function like elements
funclike := [
"Func",
"Oper",
"Constr",
"Meth",
"Filt",
"Prop",
"Attr",
"Var",
"Fam",
"InfoClass" ];
# heading comes from name of first function like element
i :=
1;
while not r.content[i].name in funclike
do
i := i+
1;
od;
f := r.content[i];
if IsBound(f.attributes.Label)
then
lab := Concatenation(
" (", f.attributes.Label,
")");
else
lab :=
"";
fi;
Append(str, Concatenation(
"\n\n\\subsection{\\textcolor{Chapter }{",
GAPDoc2LaTeXProcs.EscapeAttrVal(f.attributes.Name), lab,
"}}\n"));
# page number info for online help
Append(str, Concatenation(
"\\logpage{",
GAPDoc2LaTeXProcs.StringNrs(r.count{[
1..
3]}),
"}\\nobreak\n"));
# label for references
if IsBound(r.attributes.Label)
then
Append(str,
"\\label{");
Append(str, r.attributes.Label);
Append(str,
"}\n");
# save heading for "Text" style references to section
GAPDoc2LaTeXProcs._labeledSections.(r.attributes.Label) := Concatenation(
GAPDoc2LaTeXProcs.EscapeAttrVal(f.attributes.Name), lab);
fi;
if IsBound(r.root.six)
then
## a := First(r.root.six, x-> x[3] = r.count{[1..3]});
a := GAPDoc2LaTeXProcs.firstsix(r, r.count);
if a <> fail and IsBound(a[
7])
then
Append(str, Concatenation(
"\\hyperdef{L}{", a[
7],
"}{}\n"));
fi;
fi;
# to avoid references to local subsection in description:
GAPDoc2LaTeXProcs._currentSubsection := r.count{[
1..
3]};
Append(str,
"{");
GAPDoc2LaTeXContent(r, str);
Append(str,
"}\n\n");
Unbind(GAPDoc2LaTeXProcs._currentSubsection);
end;
GAPDoc2LaTeXProcs.Mark :=
function(r, str)
Append(str,
"\n\\item[{");
GAPDoc2LaTeXContent(r, str);
Append(str,
"}] ");
end;
GAPDoc2LaTeXProcs.Item :=
function(r, str)
Append(str,
"\n\\item ");
GAPDoc2LaTeXContent(r, str);
end;
GAPDoc2LaTeXProcs.List :=
function(r, str)
local item, type, a;
if "Mark" in List(r.content, a-> a.name)
then
item :=
"";
type :=
"description";
else
item :=
"\n\\item ";
type :=
"itemize";
fi;
Append(str, Concatenation(
"\n\\begin{", type,
"}"));
for a in r.content
do
if a.name =
"Mark" then
GAPDoc2LaTeXProcs.Mark(a, str);
elif a.name =
"Item" then
Append(str, item);
GAPDoc2LaTeXContent(a, str);
fi;
od;
Append(str, Concatenation(
"\n\\end{", type,
"}\n"));
end;
GAPDoc2LaTeXProcs.Enum :=
function(r, str)
Append(str,
"\n\\begin{enumerate}");
GAPDoc2LaTeXContent(r, str);
Append(str,
"\n\\end{enumerate}\n");
end;
GAPDoc2LaTeXProcs.TheIndex :=
function(r, str)
local a;
# page number info for online help
Append(str, Concatenation(
"\\def\\indexname{", GAPDocTexts.d.Index,
"\\logpage{", GAPDoc2LaTeXProcs.StringNrs(r.count{[
1..
3]}),
"}\n"));
if IsBound(r.root.six)
then
## a := First(r.root.six, x-> x[3] = r.count{[1..3]});
a := GAPDoc2LaTeXProcs.firstsix(r, r.count);
if a <> fail and IsBound(a[
7])
then
Append(str, Concatenation(
"\\hyperdef{L}{", a[
7],
"}{}\n"));
fi;
fi;
Append(str,
"}\n\n");
# toc entry
Append(str,
"\\cleardoublepage\n\\phantomsection\n");
Append(str,
"\\addcontentsline{toc}{chapter}{");
Append(str, GAPDocTexts.d.Index);
Append(str,
"}\n");
Append(str,
"\n\n\\printindex\n\n");
end;
# like PCDATA
GAPDoc2LaTeXProcs.EntityValue := GAPDoc2LaTeXProcs.PCDATA;
GAPDoc2LaTeXProcs.Table :=
function(r, str)
local cap;
if (IsBound(r.attributes.Only) and r.attributes.Only <>
"LaTeX") or
(IsBound(r.attributes.Not) and r.attributes.Not =
"LaTeX")
then
return;
fi;
# head part of table and tabular
if IsBound(r.attributes.Label)
then
Append(str,
"\\mbox{}\\label{");
Append(str, r.attributes.Label);
Add(str,
'}');
fi;
Append(str,
"\\begin{center}\n\\begin{tabular}{");
Append(str, r.attributes.Align);
Add(str,
'}');
# the rows of the table
GAPDoc2LaTeXContent(r, str);
# the trailing part with caption, if given
Append(str,
"\\end{tabular}\\\\[2mm]\n");
cap := Filtered(r.content, a-> a.name =
"Caption");
if Length(cap) >
0 then
GAPDoc2LaTeXProcs.Caption1(cap[
1], str);
fi;
Append(str,
"\\end{center}\n\n");
end;
# do nothing, we call .Caption1 directly in .Table
GAPDoc2LaTeXProcs.Caption :=
function(r, str)
return;
end;
# here the caption text is produced
GAPDoc2LaTeXProcs.Caption1 :=
function(r, str)
Append(str, Concatenation(
"\\textbf{", GAPDocTexts.d.Table,
": }"));
GAPDoc2LaTeXContent(r, str);
end;
GAPDoc2LaTeXProcs.HorLine :=
function(r, str)
Append(str,
"\\hline\n");
end;
GAPDoc2LaTeXProcs.Row :=
function(r, str)
local i, l;
l := Filtered(r.content, a-> a.name =
"Item");
for i in [
1..Length(l)-
1]
do
GAPDoc2LaTeXContent(l[i], str);
Append(str,
"&\n");
od;
GAPDoc2LaTeXContent(l[Length(l)], str);
Append(str,
"\\\\\n");
end;
GAPDoc2LaTeXProcs.Alt :=
function(r, str)
local take, types;
take := false;
if IsBound(r.attributes.Only)
then
NormalizeWhitespace(r.attributes.Only);
types := SplitString(r.attributes.Only,
"",
" ,");
if "LaTeX" in types or
"BibTeX" in types
then
take := true;
GAPDoc2LaTeXProcs.recode := false;
GAPDoc2LaTeXProcs.verbatimPCDATA := true;
fi;
fi;
if IsBound(r.attributes.Not)
then
NormalizeWhitespace(r.attributes.Not);
types := SplitString(r.attributes.Not,
"",
" ,");
if not
"LaTeX" in types
then
take := true;
fi;
fi;
if take
then
GAPDoc2LaTeXContent(r, str);
fi;
GAPDoc2LaTeXProcs.recode := true;
GAPDoc2LaTeXProcs.verbatimPCDATA := false;
end;
# copy a few entries with two element names
GAPDoc2LaTeXProcs.E := GAPDoc2LaTeXProcs.Emph;
GAPDoc2LaTeXProcs.Keyword := GAPDoc2LaTeXProcs.K;
GAPDoc2LaTeXProcs.Code := GAPDoc2LaTeXProcs.C;
GAPDoc2LaTeXProcs.File := GAPDoc2LaTeXProcs.F;
GAPDoc2LaTeXProcs.Button := GAPDoc2LaTeXProcs.B;
GAPDoc2LaTeXProcs.Arg := GAPDoc2LaTeXProcs.A;
GAPDoc2LaTeXProcs.Quoted := GAPDoc2LaTeXProcs.Q;
GAPDoc2LaTeXProcs.Par := GAPDoc2LaTeXProcs.P;