📄 ucommentextraction.pas
字号:
of a tabulator character)
~result the text without a tabulator characters }
function TransformTabulators(Text: String; TabWidth: Integer): String;
//maximum number of spaces to replace a tabulator character with
var Spaces :String;
Line :String; //each line of the text
TabPos :Integer; //position of next tabulator character
SpaceCount :Integer; //number of spaces to insert for a tab
begin
if Text <> '' then //something to transform tabulators in?
if Pos(#9, Text) <> 0 then //contains tabulators?
begin
Spaces := StringOfChar(' ', TabWidth - 1); //create spaces to replace with
Result := ''; //no text transformed yet
while Text <> '' do //for each line transform tabulators
begin
Line := GetLine(Text); //get next line
TabPos := Pos(#9, Line); //search first tabulator
if TabPos <> 0 then //contains at least one tabulator?
repeat //for all tabulators
Line[TabPos] := ' '; //replace it with one space
SpaceCount := TabWidth - TabPos mod TabWidth;
Inc(TabPos);
if SpaceCount <> TabWidth then //tabulator not only one space?
begin
//insert additional spaces to fill to the next tab stop
Insert(Copy(Spaces, 1, SpaceCount), Line, TabPos);
Inc(TabPos, SpaceCount);
end;
TabPos := SearchString(#9, Line, TabPos); //search next tabulator
until TabPos = 0; //until all tabulators transformed
Result := Result + Line; //add the line
if Text <> '' then //was not the last line?
Result := Result + #13#10; //end the line
end; //while Text <> ''
end //if Pos(#9, Text) <> 0
else
Result := Text //just return the text
else
Result := ''; //just return the empty text
end;
{Strips trailing whitespaces from the lines.
~param Text the text to strip whitespaces at the end of the lines
~result the text without a whitespaces at the end of lines }
function StripTrailingWhiteSpaces(Text: String): String;
begin
Result := ''; //no lines stripped so far
while Text <> '' do //for each line
begin
//get and add the line without trailing whitespaces
Result := Result + TrimRight(GetLine(Text));
if Text <> '' then //was not the last line?
Result := Result + #13#10; //end the line
end;
end;
{ * * * *** * * * *** TSectionExtractor *** * * * *** * * * }
//the number of options in this class of extractors without the names of
//the sections
const OptionCountWithoutSectionNames = 2;
{Creates the object and initializes the names of the sections.
~param Generator the generator to extract the comments for }
constructor TSectionExtractor.Create(Generator: TMakeDoc);
var First :Integer; //index of first option to be set
i :TCommentSection; //counter through sections
Value :TOptionValue; //value to set option with
begin
inherited Create(Generator); //create the object
//initialize separator of sections
FSectionSeparatorChar := DefaultSectionSeparatorChar;
FSectionNames := TStringList.Create; //create list for names of sections
FSectionNames.Sorted := True; //for faster access sort it
FSectionNames.Duplicates := dupError; //duplicates are handled manually
//get index of first option of the names of the sections
First := inherited GetOptionCount + OptionCountWithoutSectionNames -
Cardinal(Ord(Low(DefaultCommentSectionNames)));
for i := Low(DefaultCommentSectionNames) to //set all default names
High(DefaultCommentSectionNames) do
begin
Value.StrData := DefaultCommentSectionNames[i];
SetOption(First + Ord(i), Value);
end;
//create list for names of "sections" to be ignored
FIgnoredSectionNames := TStringList.Create;
FIgnoredSectionNames.Sorted := True;
FIgnoredSectionNames.Duplicates := dupIgnore;
end;
{Frees the object and the names of the sections. }
destructor TSectionExtractor.Destroy;
begin
//free list for names of "sections" to be ignored
FIgnoredSectionNames.Free;
FSectionNames.Free; //free list of the names of sections
inherited Destroy; //and this object
end;
{Returns the number of available options in extractors of this class.
~result the number of available options }
class function TSectionExtractor.GetOptionCount: Cardinal;
begin
Result := inherited GetOptionCount +
OptionCountWithoutSectionNames +
Cardinal(Ord(High(TCommentSection)) -
Ord( Low(TCommentSection)) + 1 - 1);
end;
{Gets a description of an option.
~param Index index of the option to get data of
~param Desc out: the description of the option (name, type, default value,
etc.) }
class procedure TSectionExtractor.GetOptionDescription(Index: Cardinal;
var Desc: TOptionDescription);
var PreOptionCount :Cardinal; //number of inherited options
begin
PreOptionCount := inherited GetOptionCount; //get number of inherited ones
if Index < PreOptionCount then //asked for inherited option?
inherited GetOptionDescription(Index, Desc) //forward to parent class
else
begin
ClearDescription(Desc); //clear structure
Dec(Index, PreOptionCount); //get index of local option
case Index of //depending on index of option
0: begin //set the values describing the option
Desc.Name := 'SectionSeparator';
Desc.Category := 'Comments.Sections';
Desc.Description := 'The character that starts a new section inside of comments.';
Desc.DataType := otString;
Desc.StrMaxLen := 1;
Desc.DefaultValue.StrData := DefaultSectionSeparatorChar;
end;
1: begin
Desc.Name := 'DoNotSectionize';
Desc.Category := 'Comments.Sections';
Desc.Description := 'Don''t section a comment, just treat it as the one big main comment.';
Desc.DataType := otBoolean;
end;
OptionCountWithoutSectionNames..OptionCountWithoutSectionNames +
Ord(High(TCommentSection)) - Ord(Low(TCommentSection)) - 1:
begin
Desc.Name := 'SectionName_' +
CommentSectionOptionNames[
TCommentSection(Index - OptionCountWithoutSectionNames
+ Cardinal(Ord(Succ(Low(TCommentSection)))))];
Desc.Category := 'Comments.Sections.Names';
if TCommentSection(Index - OptionCountWithoutSectionNames +
Cardinal(Ord(Succ(Low(TCommentSection))))) in
[csFirstAdditionalAttribute..csLastAdditionalAttribute] then
Desc.Description := 'The comma-separated list of words of an additional section to be included in the documentation; for the heading "localize" the text "CommentAdditionalAttribute[#]" (where [#] is the same digit).'
else
Desc.Description := 'The comma-separated list of words the section has been marked with in the comments.';
if Index <> OptionCountWithoutSectionNames then
Desc.HelpOptionIndex := PreOptionCount +
OptionCountWithoutSectionNames + 1;
Desc.Options := [ooChangesOtherOptions];
Desc.DataType := otString;
Desc.DefaultValue.StrData :=
DefaultCommentSectionNames[TCommentSection(Index -
OptionCountWithoutSectionNames +
Cardinal(Ord(Succ(Low(TCommentSection)))))];
end;
else
Assert(Index >= GetOptionCount); //invalid index!
raise EInvalidOption.Create('Invalid index for option supplied!');
end;
end;
end;
{Gets the value of an option. Call ~[link GetOptionDescription] to get the type
and the meaning of the option.
~param Index index of the option to get the value of
~result the value of the option }
function TSectionExtractor.GetOption(Index: Cardinal): TOptionValue;
{Returns all names of the specified section separated by a comma.
~param Section the seciton whose names should be returned
~result all registered names of the sectons }
function GetSectionNames(Section: TCommentSection): String;
var i :Integer; //counter through all names
begin
Result := '';
for i := 0 to FSectionNames.Count - 1 do //for each name
//if it is a name of this section?
if TCommentSection(FSectionNames.Objects[i]) = Section then
begin
if Result <> '' then //not the first name
Result := Result + ','; //add the separating comma
Result := Result + FSectionNames[i]; //add the name
end;
end;
var PreOptionCount :Cardinal; //number of inherited options
begin
PreOptionCount := inherited GetOptionCount; //get number of inherited ones
if Index < PreOptionCount then //asked for inherited option?
Result := inherited GetOption(Index) //forward to parent class
else
case Index - PreOptionCount of //depending on index of option
0: Result.StrData := FSectionSeparatorChar; //get the value
1: Result.BoolData := FDoNotSectionize;
OptionCountWithoutSectionNames..OptionCountWithoutSectionNames +
Ord(High(TCommentSection)) - Ord(Low(TCommentSection)) - 1:
Result.StrData := GetSectionNames(TCommentSection(Index -
PreOptionCount -
OptionCountWithoutSectionNames +
Cardinal(Ord(Succ(Low(TCommentSection))))));
else
Assert(Index >= GetOptionCount); //invalid index!
raise EInvalidOption.Create('Invalid index for option supplied!');
end;
end;
{Sets the value of an option. Call ~[link GetOptionDescription] to get the type
and the meaning of the option.
~param Index index of the option to set the value
~param Value the new value of the option }
procedure TSectionExtractor.SetOption(Index: Cardinal;
const Value: TOptionValue);
{Returns all names of the specified section separated by a comma.
~param Section the seciton whose names should be returned
~result all registered names of the sectons }
procedure SetSectionNames(Section: TCommentSection; const Names: String);
var i :Integer; //counter through all names
StartInd :Integer; //start index of each name
EndInd :Integer; //end index of each name
Name :String; //each part of the name
begin
//delete all old names of the section
for i := FSectionNames.Count - 1 downto 0 do
if TCommentSection(FSectionNames.Objects[i]) = Section then
FSectionNames.Delete(i);
StartInd := 1;
while StartInd < Length(Names) do //for each name
begin
EndInd := SearchString(',', Names, StartInd); //search its end
if EndInd = 0 then
EndInd := Length(Names) + 1;
Name := Copy(Names, StartInd, EndInd - StartInd); //and get it
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -