📄 uguihelpreader.pas
字号:
Generator.AddPositionMessage(Messages, Msg, Text);
end;
{Extracts the header from the documentation of a topic/component of a GUI.
~param Comment the documentation with the header that will be removed
~param ErrorMsg the text of the error message to use if no header is found
~result the header of the documentation or '' if none specified }
function TJADDGUIHelpReader.GUIHelpExtractHeader(var Comment: String;
const ErrorMsg: String): String;
var i :Integer; //index of the end of the first line
begin
i := pos(#10, Comment); //search end of line-marker
if i <> 0 then //more than one line?
begin
if (i > 1) and (Comment[i - 1] = #13) then //#13#10 ?
dec(i); //delete also the #13
Result := Copy(Comment, 1, i - 1); //extract the header
Delete(Comment, 1, i + Ord(Comment[i] <> #10)); //delete header
end
else
begin
Result := Comment; //whole comment is the header
Comment := ''; //no comment left
end;
if TrimLeft(Result) = '' then //no header found?
begin
AddMessage(jghrmkNoTopicHeading, ErrorMsg); //generate warning message
Result := ''; //return none
end;
end;
{Extracts the topics of all comments in the file.
~param Data the data to extract all topics from }
procedure TJADDGUIHelpReader.ParseTopics(Data: TOldGUIHelpData);
var i :Integer; //counter through all comments
Comment :String; //each comment
Topic :String; //the topic of each comment
begin
assert(Data.CommentCommentTopics.Count = 0);
for i := 0 to Data.CommentNames.Count - 1 do //for each documentation topic
begin
CurrentGUIHelpTopic := Data.CommentNames[i];
Comment := Data.CommentComments[i]; //get the documentation
Topic := GUIHelpExtractHeader(Comment, //extract its header
'No section heading for ' +
Data.BaseName + '.' + Data.CommentNames[i]);
Data.CommentComments[i] := Comment; //set documentation
Data.CommentCommentTopics.Add(Topic); //and its header
end;
assert(Data.CommentCommentTopics.Count = Data.CommentComments.Count);
CurrentGUIHelpTopic := GUIHelpTopicSpecialPrefix + 'Default';
Comment := Data.DefaultComment; //get the default comment
Topic := GUIHelpExtractHeader(Comment, //extract its header
'No section heading for the default comment in: ' +
Data.BaseName);
Data.DefaultComment := Comment; //set default documentation
Data.DefaultCommentTopic := Topic //and its header
end;
{Parses the sections with data of documentation to generate help on a GUI.
~param Data the data to add the parsed documentation of the file to
~param FileName the name of the file containing the documentation
~param Comment the documentation in its sections }
procedure TJADDGUIHelpReader.ParseGUISections(Data: TOldGUIHelpData;
const FileName: String;
Comment: TComment);
var Text :String; //text of each section
First, Second :String; //parameters of the section
i :Integer; //index of the component
begin
//for each ~~guialias section, get it
while Comment.GetAndDeleteSection(csGUIAlias, Text) do
begin
//get component to alias
First := Generator.Evaluator.GetInlineCommandArg(Text);
//and to alias it to
Second := Generator.Evaluator.GetInlineCommandArg(Text);
if (First <> '') and (Second <> '') and
(First[1] in StartIdentifierChars) and
(Second[1] in StartIdentifierChars + ['.']) then
Data.Aliases.Append(First + '=' + Second) //add the alias
else
AddMessage(jghrmkInvalidAliasNames,
'Not both parameters for alias given or invalid names: ' +
ExtractFileName(FileName) + ': ' + First + ' ' + Second);
end;
//for each ~~guimanual section, get it
while Comment.GetAndDeleteSection(csGUIManual, Text) do
begin
//get position of the link
First := Generator.Evaluator.GetInlineCommandArg(Text);
//get target of the link
Second := Generator.Evaluator.GetInlineCommandArg(Text);
if (First = '') or (Second = '') or not (First[1] in ['0'..'9']) or
not Data.AddManualLink(First, Second) then //add it
AddMessage(jghrmkInvalidManualLink,
'Not both position and target of manual link given or invalid position: ' +
ExtractFileName(FileName) + ': ' + First + ' ' + Second);
end;
//for each ~~gui section, get it
while Comment.GetAndDeleteSection(csGUI, Text) do
begin
//get name of the documented component
First := Trim(Generator.Evaluator.GetInlineCommandArg(Text));
//valid name for component or special documentation?
if (First <> '') and (First[1] in StartIdentifierChars + ['.']) then
begin
if First[1] = '.' then //special documentation?
begin
Delete(First, 1, 1);
First := LowerCase(First);
if First = 'default' then //default documentation?
begin
if Data.DefaultComment <> '' then
AddMessage(jghrmkDocumentationReplaced,
'Default documentation has been replaced: ' +
ExtractFileName(FileName));
Data.DefaultComment := Text;
end
else
if First = 'preface' then //the preface?
begin
if Data.Preface <> '' then
AddMessage(jghrmkDocumentationReplaced,
'Preface of documentation has been replaced: ' +
ExtractFileName(FileName));
Data.Preface := Text;
end
else
if First = 'epilogue' then //the epilogue?
begin
if Data.Epilogue <> '' then
AddMessage(jghrmkDocumentationReplaced,
'Epilogue of documentation has been replaced: ' +
ExtractFileName(FileName));
Data.Epilogue := Text;
end
else
AddMessage(jghrmkUnknownSpecialDocumentation,
'Unknown special name for documentation: ' +
ExtractFileName(FileName) + ': ' + First);
end //if First[1] = '.'
else
begin
i := Data.CommentNames.IndexOf(First); //get index of the component
if i = -1 then //component not documented yet?
begin
Data.CommentNames.Append(First); //add name of documented component
Data.CommentComments.Append(Text); //add the documentation
end
else
begin
Data.CommentNames[i] := First; //set name of documented component
Data.CommentComments[i] := Text; //set the documentation
AddMessage(jghrmkDocumentationReplaced,
'Previous documentation of component has been replaced: ' +
ExtractFileName(FileName) + ': ' + First);
end; //else i = -1
end; //else First[1] = '.'
end //if First <> '' and First[1] in StartIdentifierChars + ['.']
else
AddMessage(jghrmkInvalidTopicName,
'Invalid or no name of the component for the documentation: ' +
ExtractFileName(FileName) + ': ' + First);
end; //while GetDeleteSection(csGUIManual, ...
end;
{Reads a file of documentation for the help on a GUI.
~param Data the data to add the parsed documentation of the file to
~param FileName the name of the file to parse
~param ParsedFiles the already parsed to not parse files twice
~result the text outside sections }
function TJADDGUIHelpReader.ReadGUIDocumentationFile(Data: TOldGUIHelpData;
const FileName: String;
ParsedFiles: TStringList): String;
var Text :String; //contents of file and sections
Comment :TComment; //contents of file as sections
S :String; //general string
begin
if ParsedFiles.IndexOf(ExtractShortPathName(ExpandFileName(FileName))) =
-1 then //file not parsed yet?
begin
//add to list of already parsed files
ParsedFiles.Append(ExtractShortPathName(ExpandFileName(FileName)));
Text := '';
if ReadFileContent(FileName, Text) then //read the content of the file
begin
//get all sections in the file
Comment := Generator.Extractor.Sectionize(Text, True);
try
Result := ''; //get the text outside sections
Comment.GetAndDeleteSection(csComment, Result);
Text := '';
//for each ~~guiinclude section, get it
while Comment.GetAndDeleteSection(csGUIInclude, Text) do
begin
//get name of file to include
Text := Generator.Evaluator.GetInlineCommandArg(Text);
if Text <> '' then //file specified?
begin //get absolute path
S := GetAbsolutePathRelative(GetAbsolutePathCurrent(
ExtractFilePath(FileName)),
Text);
if FileExists(S) then //file exists?
begin
//read it, too, and check that no text is outside of sections
if TrimLeft(ReadGUIDocumentationFile(Data, S, ParsedFiles)) <>
'' then
AddMessage(jghrmkTextOutsideSection,
'Text outside of a section in file ' +
ExtractFileName(S));
end
else
AddMessage(jghrmkDocumentationFileInvalid,
'File to include not found: ' + Text +
' in file ' + ExtractFileName(FileName));
end
else
AddMessage(jghrmkDocumentationFileInvalid,
'No file to include given in file ' +
ExtractFileName(FileName));
end;
//parse the other sections
ParseGUISections(Data, FileName, Comment);
//check for further invalid sections
Generator.CheckInvalidSections(Comment);
finally
Comment.Free;
end;
end
else
AddMessage(jghrmkCantReadFile,
'Can''t read file with documentation: ' +
ExtractFileName(FileName));
end
else
AddMessage(jghrmkDoubleFiles,
'Ignoring already read file with documentation: ' +
ExtractFileName(FileName));
end;
{Read the documentation for the help on a GUI.
~param Data the data of the parsed log file for which the documentation should
be read }
procedure TJADDGUIHelpReader.ReadGUIDocumentation(Data: TOldGUIHelpData);
var FileName :String; //the name of the file
ParsedFiles :TStringList; //list of already parsed files
begin
FileName := ChangeFileExt(Data.LogFilePath, '.txt'); //get name of the file
if FileExists(FileName) then //file exists?
begin
ParsedFiles := TStringList.Create; //create list for parsed files
try
//parse the file
Data.Title := Trim(ReadGUIDocumentationFile(Data, FileName, ParsedFiles));
finally
ParsedFiles.Free; //free list for parsed files
end;
ParseTopics(Data); //parse the topics of the file
end
else
AddMessage(jghrmkDocumentationFileInvalid,
'File with documentation not found: ' +
ExtractFileName(FileName));
end;
{Parses all log files to generate a help on a GUI.
~param GUIHelpFileList the list of log files with the data of the GUI }
procedure TJADDGUIHelpReader.ParseAllLogFiles(GUIHelpFileList: TStrings);
var i :Integer; //counter through all log files
Data :TOldGUIHelpData; //each data of each file
begin
Self.GUIHelpFiles.Assign(GUIHelpFileList); //save the list
try
FCurrentGUIHelpTopic := GUIHelpTopicSpecialPrefix + 'log';
for i := 0 to GUIHelpFiles.Count - 1 do //for each log file
begin
CurrentGUIHelpFileIndex := i;
assert(IsAbsolutePath(GUIHelpFiles[i]));
Data := TOldGUIHelpData.Create(GUIHelpFiles[i], //parse it
Generator, FJADDGUIHelpMessagesID,
Ord(jghrmkLogFileInvalid));
try
FGUIHelpData.Add(Data); //and add it to the list
except
Data.Free;
raise;
end;
end;
FCurrentGUIHelpTopic := GUIHelpTopicSpecialPrefix + 'txt';
for i := 0 to FGUIHelpData.Count - 1 do //for each parsed log file
begin
FCurrentGUIHelpFileIndex := i;
ReadGUIDocumentation(FGUIHelpData[i]); //read its documentation
end;
finally
FCurrentGUIHelpFileIndex := -1; //reset the index
end;
end;
{Checks if the name is an alias and returns the final name.
~param PossibleAliasName the name that may be an alias
~param Data the data of the file
~result the real name, either PossibleAliasName or the name it is an alias
from }
function TJADDGUIHelpReader.GUIHelpUnalias(PossibleAliasName: String;
Data: TOldGUIHelpData): String;
begin
Result := Data.Aliases.Values[PossibleAliasName]; //get alias?
if (Result = '') and FGUIHelpUseAutoAliases then //no manual alias?
//check the automatic ones
Result := Data.LoggedAliases.Values[PossibleAliasName];
while Result <> '' do //is an alias?
begin
PossibleAliasName := Result; //use the original name
Result := Data.Aliases.Values[PossibleAliasName]; //check if it is also
if (Result = '') and FGUIHelpUseAutoAliases then //an alias
Result := Data.LoggedAliases.Values[PossibleAliasName];
end;
Result := PossibleAliasName; //result the final name
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -