fpc/utils/fpdoc/dw_latex.pp
2004-07-23 23:39:48 +00:00

1504 lines
38 KiB
ObjectPascal

{
$Id$
FPDoc - Free Pascal Documentation Tool
Copyright (C) 2000 - 2003 by
Areca Systems GmbH / Sebastian Guenther, sg@freepascal.org
* LaTeX output generator
See the file COPYING, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
unit dw_LaTeX;
{$MODE objfpc}
{$H+}
interface
uses DOM, dGlobals, PasTree;
const
LateXHighLight : Boolean = False;
TexExtension : String = '.tex';
procedure CreateLaTeXDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine);
implementation
uses SysUtils, Classes, dWriter;
type
TLabelType = (ltConst,ltVar,ltType,ltFunction,ltProcedure,ltClass,
ltChapter,ltSection,ltSubsection,
ltTable,ltFigure);
TLaTeXWriter = class(TFPDocWriter)
protected
f: Text;
FLink: String;
Package: TPasPackage;
PackageName: String;
Module: TPasModule;
ModuleName: String;
FTableCount : Integer;
FInVerbatim : Boolean;
TableRowStartFlag, TableCaptionWritten: Boolean;
function GetLabel(AElement: TPasElement): String;
procedure Write(const s: String);
procedure WriteF(const s: String; const Args: array of const);
procedure WriteLn(const s: String);
procedure WriteLnF(const s: String; const Args: array of const);
// Tex functions
procedure WriteLabel(El: TPasElement);
procedure WriteLabel(const s: String);
procedure WriteIndex(El: TPasElement);
procedure WriteIndex(const s: String);
procedure StartListing(Frames: Boolean; const name: String);
procedure StartListing(Frames: Boolean);
procedure EndListing;
Function EscapeTex(S : String) : String;
Function StripTex(S : String) : String;
procedure WriteCommentLine;
procedure WriteComment(Comment : String);
procedure StartSection(SectionName : String; SectionLabel : String);
procedure StartSection(SectionName : String);
procedure StartSubSection(SubSectionName : String; SubSectionLabel : String);
procedure StartSubSection(SubSectionName : String);
procedure StartChapter(ChapterName : String; ChapterLabel : String);
procedure StartChapter(ChapterName : String);
// Description node conversion
procedure DescrWriteText(const AText: DOMString); override;
procedure DescrBeginBold; override;
procedure DescrEndBold; override;
procedure DescrBeginItalic; override;
procedure DescrEndItalic; override;
procedure DescrBeginEmph; override;
procedure DescrEndEmph; override;
procedure DescrWriteFileEl(const AText: DOMString); override;
procedure DescrWriteKeywordEl(const AText: DOMString); override;
procedure DescrWriteVarEl(const AText: DOMString); override;
procedure DescrBeginLink(const AId: DOMString); override;
procedure DescrEndLink; override;
procedure DescrWriteLinebreak; override;
procedure DescrBeginParagraph; override;
procedure DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String); override;
procedure DescrWriteCodeLine(const ALine: String); override;
procedure DescrEndCode; override;
procedure DescrEndParagraph; override;
procedure DescrBeginOrderedList; override;
procedure DescrEndOrderedList; override;
procedure DescrBeginUnorderedList; override;
procedure DescrEndUnorderedList; override;
procedure DescrBeginDefinitionList; override;
procedure DescrEndDefinitionList; override;
procedure DescrBeginListItem; override;
procedure DescrEndListItem; override;
procedure DescrBeginDefinitionTerm; override;
procedure DescrEndDefinitionTerm; override;
procedure DescrBeginDefinitionEntry; override;
procedure DescrEndDefinitionEntry; override;
procedure DescrBeginSectionTitle; override;
procedure DescrBeginSectionBody; override;
procedure DescrEndSection; override;
procedure DescrBeginRemark; override;
procedure DescrEndRemark; override;
procedure DescrBeginTable(ColCount: Integer; HasBorder: Boolean); override;
procedure DescrEndTable; override;
procedure DescrBeginTableCaption; override;
procedure DescrEndTableCaption; override;
procedure DescrBeginTableHeadRow; override;
procedure DescrEndTableHeadRow; override;
procedure DescrBeginTableRow; override;
procedure DescrEndTableRow; override;
procedure DescrBeginTableCell; override;
procedure DescrEndTableCell; override;
procedure WriteDescr(Element: TPasElement);
procedure WriteDescr(AContext: TPasElement; DescrNode: TDOMElement);
function ConstValue(ConstDecl: TPasConst): String;
procedure ProcessSection(ASection: TPasSection);
// Documentation writing methods.
procedure WriteResourceStrings(ASection: TPasSection);
procedure WriteUnitOverview(ASection: TPasSection);
procedure WriteVarsConstsTypes(ASection: TPasSection);
procedure WriteConsts(ASection: TPasSection);
procedure WriteTypes(ASection: TPasSection);
procedure WriteEnumElements(TypeDecl : TPasEnumType);
procedure WriteVars(ASection: TPasSection);
procedure WriteFunctionsAndProcedures(ASection: TPasSection);
procedure WriteProcedure(ProcDecl: TPasProcedureBase);
procedure WriteClasses(ASection: TPasSection);
procedure WriteClassDecl(ClassDecl: TPasClassType);
procedure WriteClassMethodOverview(ClassDecl: TPasClassType);
procedure WriteClassPropertyOverview(ClassDecl: TPasClassType);
procedure WriteProperty(PropDecl: TPasProperty);
procedure WriteExample(ADocNode: TDocNode);
procedure WriteSeeAlso(ADocNode: TDocNode);
procedure WriteSeeAlso(ADocNode: TDocNode; InList : Boolean);
procedure SortElementList(List : TList);
Function ShowMember(M : TPasElement) : boolean;
Procedure ProcessPackage;
Procedure ProcessTopics(DocNode : TDocNode; Alevel : Integer);
Procedure WriteTopicNode(Node : TDocNode; Level : Integer);
public
constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine);
procedure WriteDoc;
end;
constructor TLaTeXWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
procedure AddLabel(AElement: TPasElement);
begin
Engine.AddLink(AElement.PathName, GetLabel(AElement));
end;
procedure AddList(AElement: TPasElement; AList: TList);
var
i: Integer;
begin
for i := 0 to AList.Count - 1 do
AddLabel(TPasElement(AList[i]));
end;
procedure AddTopicPages(AElement: TPasElement);
var
PreviousTopic,
TopicElement : TTopicElement;
DocNode,
TopicNode : TDocNode;
begin
DocNode:=Engine.FindDocNode(AElement);
If not Assigned(DocNode) then
exit;
TopicNode:=DocNode.FirstChild;
PreviousTopic:=Nil;
While Assigned(TopicNode) do
begin
If TopicNode.TopicNode then
begin
TopicElement:=TTopicElement.Create(TopicNode.Name,AElement);
Topics.Add(TopicElement);
TopicElement.TopicNode:=TopicNode;
TopicElement.Previous:=PreviousTopic;
If Assigned(PreviousTopic) then
PreviousTopic.Next:=TopicElement;
PreviousTopic:=TopicElement;
if AElement is TTopicElement then
TTopicElement(AElement).SubTopics.Add(TopicElement);
Engine.AddLink(TopicElement.PathName, GetLabel(TopicElement));
if AElement is TTopicElement then
TTopicElement(AElement).SubTopics.Add(TopicElement)
else // Only one level of recursion.
AddTopicPages(TopicElement);
end;
TopicNode:=TopicNode.NextSibling;
end;
end;
procedure ScanModule(AModule: TPasModule);
var
i, j, k: Integer;
s: String;
ClassEl: TPasClassType;
FPEl, AncestorMemberEl: TPasElement;
DocNode: TDocNode;
DidAutolink: Boolean;
begin
AddLabel(AModule);
AddTopicPages(AModule);
with AModule do
begin
AddList(AModule, InterfaceSection.ResStrings);
AddList(AModule, InterfaceSection.Consts);
AddList(AModule, InterfaceSection.Types);
if InterfaceSection.Classes.Count > 0 then
begin
for i := 0 to InterfaceSection.Classes.Count - 1 do
begin
ClassEl := TPasClassType(InterfaceSection.Classes[i]);
AddLabel(ClassEl);
for j := 0 to ClassEl.Members.Count - 1 do
begin
FPEl := TPasElement(ClassEl.Members[j]);
if ((FPEl.Visibility = visPrivate) and Engine.HidePrivate) or
((FPEl.Visibility = visProtected) and Engine.HideProtected) then
continue;
DocNode := Engine.FindDocNode(FPEl);
if not Assigned(DocNode) then
begin
DidAutolink := False;
if Assigned(ClassEl.AncestorType) and
(ClassEl.AncestorType.ClassType = TPasClassType) then
begin
for k := 0 to TPasClassType(ClassEl.AncestorType).Members.Count - 1 do
begin
AncestorMemberEl :=
TPasElement(TPasClassType(ClassEl.AncestorType).Members[k]);
if AncestorMemberEl.Name = FPEl.Name then
begin
DocNode := Engine.FindDocNode(AncestorMemberEl);
if Assigned(DocNode) then
begin
DidAutolink := True;
Engine.AddLink(FPEl.PathName,
Engine.FindAbsoluteLink(AncestorMemberEl.PathName));
break;
end;
end;
end;
end;
if not DidAutolink then
AddLabel(FPEl);
end else
AddLabel(FPEl);
end;
end;
end;
AddList(AModule, InterfaceSection.Functions);
AddList(AModule, InterfaceSection.Variables);
end;
end;
var
i: Integer;
begin
inherited Create(AEngine);
Package := APackage;
{ Allocate labels for all elements for which we are going to create
documentation. This is needed for links to work correctly. }
// Allocate label for the package itself, if a name is given (i.e. <> '#')
if Length(Package.Name) > 1 then
begin
AddLabel(Package);
AddTopicPages(Package);
end;
for i := 0 to Package.Modules.Count - 1 do
ScanModule(TPasModule(Package.Modules[i]));
end;
Procedure TLatexWriter.ProcessPackage;
var
i: Integer;
UnitRef: TPasType;
DocNode: TDocNode;
First : Boolean;
begin
DocNode:=Engine.FindDocNode(Package);
if Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr) then
begin
WriteLnF('\section{%s}', [EscapeTex(SDocOverview)]);
WriteDescr(Package, DocNode.Descr);
Writeln('');
end;
WriteSeeAlso(DocNode,True);
ProcessTopics(DocNode,1);
end;
Procedure TlatexWriter.ProcessTopics(DocNode : TDocNode; Alevel : Integer);
Var
Node : TDocNode;
First : Boolean;
begin
If Not Assigned(DocNode) then
Exit;
Node:=DocNode.FirstChild;
First:=True;
While Assigned(Node) do
begin
If Node.TopicNode then
begin
WriteTopicNode(Node,ALevel);
First:=False;
end;
Node:=Node.NextSibling;
end;
end;
Procedure TLatexWriter.WriteTopicNode(Node : TDocNode; Level : Integer);
Var
Element : TTopicElement;
SubNode : TDocNode;
begin
Element:=FindTopicElement(Node);
If Not Assigned(Element) then
Exit;
Case Level of
1 : Write('\section{');
2 : Write('\subsection{');
3 : Write('\subsubsection{');
end;
WriteDescr(Element,Node.ShortDescr);
Writeln('}');
WriteLabel(Element);
If Assigned(Node.Descr) then
WriteDescr(Element,Node.Descr);
WriteSeeAlso(Node,True);
If Level<3 then
begin
SubNode:=Node.FirstChild;
While Assigned(SubNode) do
begin
If SubNode.TopicNode then
WriteTopicNode(SubNode,Level+1);
SubNode:=SubNode.NextSibling;
end;
end;
end;
procedure TLaTeXWriter.WriteDoc;
var
i : Integer;
DocNode : TDocNode;
begin
PackageName := LowerCase(Copy(Package.Name, 2, 255));
If (Engine.OutPut='') then
Engine.Output:=PackageName+TexExtension;
Assign(f, Engine.Output);
Rewrite(f);
try
WriteLn('% This file has been created automatically by FPDoc,');
WriteLn('% (c) 2000-2003 by Areca Systems GmbH / Sebastian Guenther (sg@freepascal.org)');
ProcessPackage;
for i := 0 to Package.Modules.Count - 1 do
begin
Module := TPasModule(Package.Modules[i]);
ModuleName := LowerCase(Module.Name);
WriteLn('');
WriteLnF('\chapter{%s}', [EscapeTex(Format(SDocUnitTitle, [Module.Name]))]);
WriteLabel(Module);
DocNode:=Engine.FindDocNode(Module);
If Assigned(DocNode) then
ProcessTopics(DocNode,1);
ProcessSection(Module.InterfaceSection);
end;
finally
Close(f);
end;
end;
function TLaTeXWriter.GetLabel(AElement: TPasElement): String;
var
i: Integer;
begin
if AElement.ClassType = TPasUnresolvedTypeRef then
Result := Engine.ResolveLink(Module, AElement.Name)
else
begin
Result := AElement.PathName;
Result := LowerCase(Copy(Result, 2, Length(Result) - 1));
end;
for i := 1 to Length(Result) do
if Result[i] = '.' then
Result[i] := ':';
end;
procedure TLaTeXWriter.Write(const s: String);
begin
System.Write(f, s);
end;
procedure TLaTeXWriter.WriteF(const s: String; const Args: array of const);
begin
System.Write(f, Format(s, Args));
end;
procedure TLaTeXWriter.WriteLn(const s: String);
begin
System.WriteLn(f, s);
end;
procedure TLaTeXWriter.WriteLnF(const s: String; const Args: array of const);
begin
System.WriteLn(f, Format(s, Args));
end;
Function TLatexWriter.EscapeTex(S : String) : String;
var
i: Integer;
begin
if FInVerBatim=True then
Result:=S
else
begin
SetLength(Result, 0);
for i := 1 to Length(S) do
case S[i] of
'&','{','}','#','_','$','%': // Escape these characters
Result := Result + '\' + S[i];
'~','^':
Result := Result + '\'+S[i]+' ';
'\':
Result:=Result+'$\backslash$'
else
Result := Result + S[i];
end;
end;
end;
Function TLatexWriter.StripTex(S : String) : String;
var
I,L: Integer;
begin
SetLength(Result, 0);
for i := 1 to Length(S) do
If not (S[i] in ['&','{','}','#','_','$','%','''','~','^', '\']) then
Result := Result + S[i];
end;
procedure TLaTeXWriter.DescrWriteText(const AText: DOMString);
begin
Write(EscapeTex(AText));
end;
procedure TLaTeXWriter.DescrBeginBold;
begin
Write('\textbf{');
end;
procedure TLaTeXWriter.DescrEndBold;
begin
Write('}');
end;
procedure TLaTeXWriter.DescrBeginItalic;
begin
Write('\textit{');
end;
procedure TLaTeXWriter.DescrEndItalic;
begin
Write('}');
end;
procedure TLaTeXWriter.DescrBeginEmph;
begin
Write('\emph{');
end;
procedure TLaTeXWriter.DescrEndEmph;
begin
Write('}');
end;
procedure TLaTeXWriter.DescrWriteFileEl(const AText: DOMString);
begin
Write('\file{');
DescrWriteText(AText);
Write('}');
end;
procedure TLaTeXWriter.DescrWriteKeywordEl(const AText: DOMString);
begin
Write('\textbf{\\ttfamily ');
DescrWriteText(AText);
Write('}');
end;
procedure TLaTeXWriter.DescrWriteVarEl(const AText: DOMString);
begin
Write('\var{');
DescrWriteText(AText);
Write('}');
end;
procedure TLaTeXWriter.DescrBeginLink(const AId: DOMString);
var
i: Integer;
begin
FLink := Engine.ResolveLink(Module, AId);
// System.WriteLn('Link "', AId, '" => ', FLink);
end;
procedure TLaTeXWriter.DescrEndLink;
begin
WriteF(' (\pageref{%s})',[StripTex(Flink)]);
end;
procedure TLaTeXWriter.DescrWriteLinebreak;
begin
WriteLn('\\');
end;
procedure TLaTeXWriter.DescrBeginParagraph;
begin
// Do nothing
end;
procedure TLaTeXWriter.DescrEndParagraph;
begin
WriteLn('');
WriteLn('');
end;
procedure TLaTeXWriter.DescrBeginCode(HasBorder: Boolean;
const AHighlighterName: String);
begin
StartListing(HasBorder);
end;
procedure TLaTeXWriter.DescrWriteCodeLine(const ALine: String);
begin
WriteLn(ALine);
end;
procedure TLaTeXWriter.DescrEndCode;
begin
EndListing
end;
procedure TLaTeXWriter.DescrBeginOrderedList;
begin
WriteLn('\begin{enumerate}');
end;
procedure TLaTeXWriter.DescrEndOrderedList;
begin
WriteLn('\end{enumerate}');
end;
procedure TLaTeXWriter.DescrBeginUnorderedList;
begin
WriteLn('\begin{itemize}');
end;
procedure TLaTeXWriter.DescrEndUnorderedList;
begin
WriteLn('\end{itemize}');
end;
procedure TLaTeXWriter.DescrBeginDefinitionList;
begin
WriteLn('\begin{description');
end;
procedure TLaTeXWriter.DescrEndDefinitionList;
begin
WriteLn('\end{description}');
end;
procedure TLaTeXWriter.DescrBeginListItem;
begin
Write('\item ');
end;
procedure TLaTeXWriter.DescrEndListItem;
begin
WriteLn('');
end;
procedure TLaTeXWriter.DescrBeginDefinitionTerm;
begin
Write('\item[');
end;
procedure TLaTeXWriter.DescrEndDefinitionTerm;
begin
WriteLn(']');
end;
procedure TLaTeXWriter.DescrBeginDefinitionEntry;
begin
// Do nothing
end;
procedure TLaTeXWriter.DescrEndDefinitionEntry;
begin
WriteLn('');
end;
procedure TLaTeXWriter.DescrBeginSectionTitle;
begin
Write('\subsection{');
end;
procedure TLaTeXWriter.DescrBeginSectionBody;
begin
WriteLn('}');
end;
procedure TLaTeXWriter.DescrEndSection;
begin
// Do noting
end;
procedure TLaTeXWriter.DescrBeginRemark;
begin
WriteLn('\begin{remark}');
end;
procedure TLaTeXWriter.DescrEndRemark;
begin
WriteLn('\end{remark}');
end;
procedure TLaTeXWriter.DescrBeginTable(ColCount: Integer; HasBorder: Boolean);
var
i: Integer;
begin
// !!!: How do we set the border?
Write('\begin{FPCltable}{');
for i := 1 to ColCount do
Write('l');
write('}{');
TableCaptionWritten:=False;
end;
procedure TLaTeXWriter.DescrEndTable;
begin
WriteLn('\end{FPCltable}');
end;
procedure TLaTeXWriter.DescrBeginTableCaption;
begin
// Do nothing.
end;
procedure TLaTeXWriter.DescrEndTableCaption;
begin
Write('}{table');
Inc(FTableCount);
Write(IntToStr(FTableCount));
Writeln('}');
TableCaptionWritten := True;
end;
procedure TLaTeXWriter.DescrBeginTableHeadRow;
begin
if not TableCaptionWritten then
DescrEndTableCaption;
TableRowStartFlag := True;
end;
procedure TLaTeXWriter.DescrEndTableHeadRow;
begin
WriteLn('\\ \hline');
end;
procedure TLaTeXWriter.DescrBeginTableRow;
begin
if not TableCaptionWritten then
DescrEndTableCaption;
TableRowStartFlag := True;
end;
procedure TLaTeXWriter.DescrEndTableRow;
begin
WriteLn('\\');
end;
procedure TLaTeXWriter.DescrBeginTableCell;
begin
if TableRowStartFlag then
TableRowStartFlag := False
else
Write(' & ');
end;
procedure TLaTeXWriter.DescrEndTableCell;
begin
// Do nothing
end;
procedure TLaTeXWriter.WriteDescr(Element: TPasElement);
var
DocNode: TDocNode;
begin
DocNode := Engine.FindDocNode(Element);
if Assigned(DocNode) then
begin
if not IsDescrNodeEmpty(DocNode.Descr) then
WriteDescr(Element, DocNode.Descr)
else if not IsDescrNodeEmpty(DocNode.ShortDescr) then
WriteDescr(Element, DocNode.ShortDescr);
end;
end;
procedure TLaTeXWriter.WriteDescr(AContext: TPasElement; DescrNode: TDOMElement);
begin
if Assigned(DescrNode) then
ConvertDescr(AContext, DescrNode, False);
end;
function TLaTeXWriter.ConstValue(ConstDecl: TPasConst): String;
begin
if Assigned(ConstDecl) then
Result := ConstDecl.ClassName
else
Result := '<nil>';
end;
procedure TLaTexWriter.WriteUnitOverview(ASection: TPasSection);
var
i: Integer;
UnitRef: TPasType;
DocNode: TDocNode;
begin
if ASection.UsesList.Count > 0 then
begin
WriteLnF('\section{%s}', [SDocUsedUnits]);
WriteLnF('\begin{FPCltable}{lr}{%s}{%s:0units}',
[Format(SDocUsedUnitsByUnitXY, [Module.Name]), ModuleName]);
WriteLn('Name & Page \\ \hline');
for i := 0 to ASection.UsesList.Count - 1 do
begin
UnitRef := TPasType(ASection.UsesList[i]);
WriteLnF('%s\index{unit!%s} & \pageref{%s} \\',
[UnitRef.Name, UnitRef.Name, StripTex(GetLabel(UnitRef))]);
end;
WriteLn('\end{FPCltable}');
end;
DocNode := Engine.FindDocNode(ASection.Parent);
if Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr) then
begin
WriteLnF('\section{%s}', [EscapeTex(SDocOverview)]);
WriteDescr(ASection.Parent, DocNode.Descr);
Writeln('');
end;
end;
procedure TLaTeXWriter.WriteResourceStrings(ASection: TPasSection);
var
ResStrDecl: TPasResString;
i: Integer;
begin
if ASection.ResStrings.Count > 0 then
begin
StartSubSection(SDocResStrings,ModuleName+'ResStrings');
for i := 0 to ASection.ResStrings.Count - 1 do
begin
ResStrDecl := TPasResString(ASection.ResStrings[i]);
StartListing(false, '');
Writeln(ResStrDecl.GetDeclaration(True));
EndListing;
WriteLabel(ResStrDecl);
WriteIndex(ResStrDecl);
WriteDescr(ResStrDecl);
Writeln('');
end;
end;
end;
procedure TLaTeXWriter.WriteConsts(ASection: TPasSection);
var
i: Integer;
ConstDecl: TPasConst;
begin
if ASection.Consts.Count > 0 then
begin
WriteLnF('\subsection{%s}\label{suse:%sConstants}',
[EscapeTex(SDocConstants), EscapeTex(ModuleName)]);
for i := 0 to ASection.Consts.Count - 1 do
begin
ConstDecl := TPasConst(ASection.Consts[i]);
StartListing(False);
WriteLn(EscapeTex(ConstDecl.GetDeclaration(True)));
EndListing;
WriteLabel(ConstDecl);
WriteIndex(ConstDecl);
WriteDescr(ConstDecl);
end;
end;
end;
procedure TLaTeXWriter.WriteEnumElements(TypeDecl : TPasEnumType);
Var
EV : TPasEnumValue;
I : Integer;
DocNode : TDocNode;
begin
With TypeDecl do
begin
SortElementList(Values);
DescrBeginTable(2,True);
DescrBeginTableCaption;
Writeln(EscapeTex(Format(SDocValuesForEnum,[TypeDecl.Name])));
DescrEndTableCaption;
DescrBeginTableHeadRow;
DescrBeginTableCell;
Writeln(EscapeTex(SDocValue));
DescrEndTableCell;
DescrBeginTableCell;
Writeln(EscapeTex(SDocExplanation));
DescrEndTableCell;
DescrEndTableHeadRow;
For I:=0 to Values.Count-1 do
begin
EV:=TPasEnumValue(Values[i]);
DescrBeginTableRow;
DescrBeginTableCell;
Writeln(EscapeTex(EV.Name));
DescrEndTableCell;
DescrBeginTableCell;
DocNode := Engine.FindDocNode(EV);
if Assigned(DocNode) and (not IsDescrNodeEmpty(DocNode.ShortDescr)) then
WriteDescr(EV,DocNode.ShortDescr);
DescrEndTableCell;
DescrEndTableRow;
end;
DescrEndTable;
end;
end;
procedure TLaTeXWriter.WriteTypes(ASection: TPasSection);
var
i: Integer;
TypeDecl: TPasType;
begin
if ASection.Types.Count > 0 then
begin
StartSubSection(SDocTypes,ModuleName+'Types');
for i := 0 to ASection.Types.Count - 1 do
begin
TypeDecl := TPasType(ASection.Types[i]);
StartListing(False);
Writeln(EscapeTex(TypeDecl.GetDeclaration(True)));
EndListing;
WriteLabel(TypeDecl);
WriteIndex(TypeDecl);
If TypeDecl is TPasEnumType then
begin
WriteENumElements(TypeDecl as TPasEnumType);
end;
WriteDescr(TypeDecl);
end;
end;
end;
procedure TLaTeXWriter.WriteVars(ASection: TPasSection);
var
VarDecl: TPasVariable;
i: Integer;
begin
if ASection.Variables.Count > 0 then
begin
StartSubsection(SDocVariables,ModuleName+'Variables');
for i := 0 to ASection.Variables.Count - 1 do
begin
VarDecl := TPasVariable(ASection.Variables[i]);
StartListing(False);
WriteLn(EscapeTex(VarDecl.GetDeclaration(True)));
EndListing;
WriteLabel(VarDecl);
WriteIndex(VarDecl);
WriteDescr(VarDecl);
end;
end;
end;
procedure TLaTeXWriter.WriteVarsConstsTypes(ASection: TPasSection);
begin
With Asection do
if (Consts.Count > 0) or
(Types.Count > 0) or
(Variables.Count > 0) or
(ResStrings.Count>0) then
begin
StartSection(SDocConstsTypesVars, ModuleName+'ConstsTypesVars');
WriteResourceStrings(ASection);
WriteConsts(ASection);
WriteTypes(ASection);
WriteVars(ASection);
end;
end;
const
SVisibility: array[TPasMemberVisibility] of string =
('Default', 'Private', 'Protected', 'Public',
'Published', 'Automated');
procedure TLatexWriter.WriteProcedure(ProcDecl : TPasProcedureBase);
var
DocNode: TDocNode;
OP : TPasOverloadedProc;
i : integer;
begin
With ProcDecl do
begin
if Not (Assigned(Parent) and Parent.InheritsFrom(TPasClassType)) then
begin
StartSubSection(Name);
WriteLabel(ProcDecl);
WriteIndex(ProcDecl);
end
else
begin // Parent assigned and hence method.
StartSubSection(Parent.Name+'.'+Name);
WriteLabel(ProcDecl);
WriteIndex(Parent.Name+'.'+Name);
end;
Writeln('\begin{FPCList}');
DocNode := Engine.FindDocNode(ProcDecl);
if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
begin
Writeln('\Synopsis');
WriteDescr(ProcDecl, DocNode.ShortDescr);
end;
Writeln('\Declaration ');
StartListing(False);
if ClassType = TPasOverloadedProc then
begin
OP:=TPasOverloadedProc(ProcDecl);
for i := 0 to OP.Overloads.Count - 1 do
begin
WriteLn(TPasProcedure(OP.Overloads[i]).GetDeclaration(True));
end;
end
else
WriteLn(GetDeclaration(True));
EndListing;
If Assigned(Parent) then
begin
Writeln('\Visibility');
Writeln(VisibilityNames[Visibility])
end;
if Assigned(DocNode) and Assigned(DocNode.Descr) then
begin
Writeln('\Description');
WriteDescr(ProcDecl);
end;
if Assigned(DocNode) and Assigned(DocNode.ErrorsDoc) then
begin
Writeln('\Errors');
WriteDescr(ProcDecl, DocNode.ErrorsDoc);
end;
WriteSeeAlso(DocNode);
Writeln('\end{FPCList}');
WriteExample(DocNode);
end;
end;
procedure TLaTeXWriter.WriteFunctionsAndProcedures(ASection: TPasSection);
var
i: Integer;
begin
if ASection.Functions.Count > 0 then
begin
StartSection(SDocProceduresAndFunctions,ModuleName+'Functions');
for i := 0 to ASection.Functions.Count - 1 do
WriteProcedure(TPasProcedureBase(ASection.Functions[i]));
end;
end;
procedure TlatexWriter.WriteExample(ADocNode: TDocNode);
var
Example: TDOMElement;
begin
if Assigned(ADocNode) then
begin
Example := ADocNode.FirstExample;
while Assigned(Example) do
begin
WritelnF('\FPCexample{%s}', [Engine.GetExampleFileName(Example)]);
if Assigned(Example.NextSibling) then
WriteLn('');
Example := TDomElement(Example.NextSibling);
end;
end;
end;
procedure TLateXWriter.WriteSeeAlso(ADocNode: TDocNode);
begin
WriteSeeAlso(ADocNode,False);
end;
procedure TLateXWriter.WriteSeeAlso(ADocNode: TDocNode; InList : Boolean);
var
Node: TDOMNode;
s: String;
First : Boolean;
begin
if Not (Assigned(ADocNode) and Assigned(ADocNode.SeeAlso)) then
Exit;
Node := ADocNode.SeeAlso.FirstChild;
First:=True;
while Assigned(Node) do
begin
if (Node.NodeType = ELEMENT_NODE) and
(Node.NodeName = 'link') then
begin
If First then
begin
If InList then
begin
Writeln('');
Writeln('\begin{FPCList}');
end;
Writeln('\SeeAlso');
First:=False;
end
else
Writeln(',');
S:=TDomElement(Node)['id'];
DescrBeginLink(S);
Writeln(S);
DescrEndLink();
end;
Node:=Node.NextSibling;
end;
If Inlist and Not First then
Writeln('\end{FPCList}');
end;
procedure TLaTeXWriter.WriteClasses(ASection: TPasSection);
var
i: Integer;
begin
if (ASection.Classes.Count > 0) then
begin
for i := 0 to ASection.Classes.Count - 1 do
WriteClassDecl(TPasClassType(ASection.Classes[i]));
end;
end;
procedure TLaTeXWriter.ProcessSection(ASection: TPasSection);
begin
With ASection do
begin
SortElementList(UsesList);
SortElementList(Declarations);
SortElementList(ResStrings);
SortElementList(Types);
SortElementList(Consts);
SortElementList(Classes);
SortElementList(Functions);
SortElementList(Variables);
end;
WriteUnitOverView(ASection);
WriteVarsConstsTypes(ASection);
WriteFunctionsAndProcedures(ASection);
WriteClasses(ASection);
end;
Function TLatexWriter.ShowMember(M : TPasElement) : boolean;
begin
Result:=not ((M.Visibility=visPrivate) and Engine.HidePrivate);
If Result then
Result:=Not ((M.Visibility=visProtected) and Engine.HideProtected)
end;
procedure TLatexWriter.WriteClassMethodOverview(ClassDecl : TPasClassType);
var
Member: TPasElement;
i, j: Integer;
s: String;
Arg: TPasArgument;
DocNode: TDocNode;
List : TStringList;
begin
List:=TStringList.Create;
Try
List.Sorted:=True;
for i := 0 to ClassDecl.Members.Count - 1 do
begin
Member := TPasElement(ClassDecl.Members[i]);
With Member do
if InheritsFrom(TPasProcedureBase) and ShowMember(Member) then
List.AddObject(Member.Name,Member);
end;
If List.Count>0 then
begin
StartSubSection(SDocMethodOverview);
WriteLabel(GetLabel(ClassDecl) + ':Methods');
WriteLn('\begin{tabularx}{\textwidth}{llX}');
WriteLnF('%s & %s & %s \\ \hline', [EscapeTex(SDocPage), EscapeTex(SDocMethod), EscapeTex(SDocDescription)]);
For I:=0 to List.Count-1 do
begin
Member:=TPasElement(List.Objects[i]);
DocNode := Engine.FindDocNode(Member);
WriteF('\pageref{%s} & %s & ',[StripTex(GetLabel(Member)), EscapeTex(Member.Name)]);
if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
WriteDescr(Member, DocNode.ShortDescr);
WriteLn('\\');
end;
WriteLn('\hline');
WriteLn('\end{tabularx}');
end;
Finally
List.Free;
end;
end;
procedure TLatexWriter.WriteClassPropertyOverview(ClassDecl : TPasClassType);
var
Member: TPasElement;
i, j: Integer;
s: String;
Arg: TPasArgument;
DocNode: TDocNode;
List : TStringList;
begin
// Write property overview
List:=TStringList.Create;
Try
List.Sorted:=True;
for i := 0 to ClassDecl.Members.Count - 1 do
begin
Member := TPasElement(ClassDecl.Members[i]);
With Member do
if InheritsFrom(TPasProperty) and SHowMember(Member) then
List.AddObject(Member.Name,Member)
end;
If (List.Count>0) then
begin
StartSubSection(SDocPropertyOverview);
WriteLabel(GetLabel(ClassDecl) + ':Properties');
WriteLn('\begin{tabularx}{\textwidth}{lllX}');
WriteLnF('%s & %s & %s & %s \\ \hline',
[EscapeTex(SDocPage), EscapeTex(SDocProperty), EscapeTex(SDocAccess), EscapeTex(SDocDescription)]);
For I:=0 to List.Count-1 do
begin
Member:=TPasElement(List.objects[i]);
WriteF('\pageref{%s} & %s & ', [StripTex(GetLabel(Member)), EscapeTex(Member.Name)]);
setlength(S,0);
if Length(TPasProperty(Member).ReadAccessorName) > 0 then
s := s + 'r';
if Length(TPasProperty(Member).WriteAccessorName) > 0 then
s := s + 'w';
if Length(TPasProperty(Member).StoredAccessorName) > 0 then
s := s + 's';
Write(s + ' & ');
DocNode := Engine.FindDocNode(Member);
if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
WriteDescr(Member, DocNode.ShortDescr);
WriteLn('\\');
end;
WriteLn('\hline');
WriteLn('\end{tabularx}');
end;
Finally
List.Free;
end;
end;
procedure TLaTeXWriter.WriteClassDecl(ClassDecl: TPasClassType);
var
DocNode: TDocNode;
Vis: TPasMemberVisibilities;
Member: TPasElement;
i: Integer;
begin
StartSection(ClassDecl.Name);
WriteLabel(ClassDecl);
WriteIndex(ClassDecl);
DocNode := Engine.FindDocNode(ClassDecl);
if Assigned(DocNode) and ((not IsDescrNodeEmpty(DocNode.Descr)) or
(not IsDescrNodeEmpty(DocNode.ShortDescr))) then
begin
StartSubSection(SDocDescription);
WriteDescr(ClassDecl);
end;
// Write method overview
WriteClassMethodOverView(ClassDecl);
// Write Property Overview;
WriteClassPropertyOverView(ClassDecl);
// Write method & property descriptions
// Determine visibilities
Vis := AllVisibilities;
if Engine.HidePrivate then
Exclude(Vis,visPrivate);
if Engine.HideProtected then
Exclude(Vis,visProtected);
for i := 0 to ClassDecl.Members.Count - 1 do
begin
Member := TPasElement(ClassDecl.Members[i]);
if ((Member.InheritsFrom(TPasProcedureBase)) and
(Member.Visibility in Vis)) then
WriteProcedure(TPasProcedureBase(Member));
end;
// properties.
for i := 0 to ClassDecl.Members.Count - 1 do
begin
Member := TPasElement(ClassDecl.Members[i]);
if ((Member.InheritsFrom(TPasProperty)) and
(Member.Visibility in Vis)) then
WriteProperty(TPasProperty(Member));
end;
end;
procedure TLaTexWriter.WriteProperty(PropDecl : TPasProperty);
var
DocNode: TDocNode;
S: String;
begin
With PropDecl do
begin
StartSubSection(Parent.Name+'.'+Name);
WriteLabel(PropDecl);
WriteIndex(Parent.Name+'.'+Name);
Writeln('\begin{FPCList}');
DocNode := Engine.FindDocNode(PropDecl);
if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
begin
Writeln('\Synopsis');
WriteDescr(PropDecl, DocNode.ShortDescr);
end;
Writeln('\Declaration ');
StartListing(False);
WriteLn('Property '+GetDeclaration(True));
EndListing;
If Assigned(Parent) then
begin
Writeln('\Visibility');
Writeln(VisibilityNames[Visibility])
end;
Writeln('\Access');
Setlength(S,0);
If Length(ReadAccessorName) > 0 then
S:='Read';
if Length(WriteAccessorName) > 0 then
begin
If S<>'' then
S:=S+',';
S:=S+'Write';
end;
Writeln(S);
if Assigned(DocNode) and Assigned(DocNode.Descr) then
begin
Writeln('\Description');
WriteDescr(PropDecl);
end;
if Assigned(DocNode) and Assigned(DocNode.ErrorsDoc) then
begin
Writeln('\Errors');
WriteDescr(PropDecl, DocNode.ErrorsDoc);
end;
WriteSeeAlso(DocNode);
Writeln('\end{FPCList}');
WriteExample(DocNode);
end;
end;
Function CompareElements(P1,P2 : Pointer) : Integer;
begin
Result:=CompareText(TPasElement(P1).Name,TPasElement(P2).Name);
end;
procedure TLaTeXWriter.SortElementList(List : TList);
begin
List.Sort(@CompareElements)
end;
procedure TLaTeXWriter.WriteLabel(El: TPasElement);
begin
WriteLabel(GetLabel(El));
end;
procedure TLaTeXWriter.WriteLabel(const s: String);
begin
WriteLnF('\label{%s}', [LowerCase(StripTex(s))]);
end;
procedure TLaTeXWriter.WriteIndex(El : TPasElement);
begin
WriteIndex(El.Name);
end;
procedure TLaTeXWriter.WriteIndex(const s : String);
begin
Write('\index{');
Write(EscapeTex(s));
Writeln('}');
end;
procedure TLaTeXWriter.StartListing(Frames: Boolean; const name: String);
begin
FInVerbatim:=True;
if Not LaTexHighLight then
begin
Writeln('');
Writeln('\begin{verbatim}');
end
else
if Frames then
Writelnf('\begin{lstlisting}{%s}',[StripTex(Name)])
else
Writelnf('\begin{lstlisting}[frame=]{%s}',[StripTex(Name)]);
end;
procedure TLaTeXWriter.StartListing(Frames : Boolean);
begin
StartListing(Frames,'');
end;
procedure TLaTeXWriter.EndListing;
begin
FInVerbatim:=False;
If LaTexHighLight then
Writeln('\end{lstlisting}')
else
Writeln('\end{verbatim}')
end;
procedure TLatexWriter.WriteCommentLine;
const
CommentLine =
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';
begin
Writeln(CommentLine);
end;
procedure TLatexWriter.WriteComment(Comment : String);
begin
Write('% ');
Writeln(Comment);
end;
procedure TLatexWriter.StartSection(SectionName : String; SectionLabel : String);
begin
StartSection(SectionName);
WriteLabel(SectionLabel);
end;
procedure TLatexWriter.StartSection(SectionName : String);
begin
Writeln('');
WriteCommentLine;
WriteComment(SectionName);
Writeln('\section{'+EscapeTex(SectionName)+'}');
end;
procedure TLatexWriter.StartSubSection(SubSectionName : String; SubSectionLabel : String);
begin
StartSubSection(SubSectionName);
WriteLabel(SubsectionLabel);
end;
procedure TLatexWriter.StartSubSection(SubSectionName : String);
begin
Writeln('');
WriteComment(SubsectionName);
Writeln('\subsection{'+EscapeTex(SubSectionName)+'}');
end;
procedure TLatexWriter.StartChapter(ChapterName : String; ChapterLabel : String);
begin
StartChapter(ChapterName);
WriteLabel(ChapterLabel);
end;
procedure TLatexWriter.StartChapter(ChapterName : String);
begin
Writeln('');
WriteCommentLine;
WriteComment(ChapterName);
WriteCommentLine;
Writeln('\chapter{'+EscapeTex(ChapterName)+'}');
end;
procedure CreateLaTeXDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine);
var
Writer: TLaTeXWriter;
begin
Writer := TLaTeXWriter.Create(APackage, AEngine);
try
Writer.WriteDoc;
finally
Writer.Free;
end;
end;
end.
{
$Log$
Revision 1.6 2004-07-23 23:39:48 michael
+ Some fixes in verbatim writing
Revision 1.5 2004/06/06 10:53:02 michael
+ Added Topic support
Revision 1.4 2003/03/18 19:28:44 michael
+ Some changes to output handling, more suitable for tex output
Revision 1.3 2003/03/18 19:12:29 michael
+ More EscapeTex calls needed
Revision 1.2 2003/03/18 01:11:51 michael
+ Some fixes to deal with illegal tex characters
Revision 1.1 2003/03/17 23:03:20 michael
+ Initial import in CVS
Revision 1.13 2003/03/13 22:02:13 sg
* New version with many bugfixes and our own parser (now independent of the
compiler source)
Revision 1.12 2002/10/20 22:49:31 michael
+ Sorted all overviews. Added table with enumeration values for enumerated types.
Revision 1.11 2002/05/24 00:13:22 sg
* much improved new version, including many linking and output fixes
Revision 1.10 2002/03/12 10:58:36 sg
* reworked linking engine and internal structure
Revision 1.9 2002/01/20 11:19:55 michael
+ Added link attribute and property to TFPElement
Revision 1.8 2002/01/08 13:00:06 michael
+ Added correct array handling and syntax highlighting is now optional
Revision 1.7 2002/01/08 08:22:40 michael
+ Implemented latex writer
Revision 1.6 2001/12/17 14:41:42 michael
+ Split out of latex writer
Revision 1.5 2001/12/17 13:41:18 jonas
* OsPathSeparator -> PathDelim
}