📄 ucommentextraction.pas
字号:
StartInd := EndInd + 1; //skip to the next name
i := FSectionNames.IndexOf(Name);
if i <> -1 then //another section's name?
FSectionNames.Objects[i] := TObject(Section) //just change it
else
FSectionNames.AddObject(Name, TObject(Section)); //add section's 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?
inherited SetOption(Index, Value) //forward to parent class
else
case Index - PreOptionCount of //depending on index of option
0: if Value.StrData <> '' then //set the value
FSectionSeparatorChar := Value.StrData[1]
else
FSectionSeparatorChar := #0;
1: FDoNotSectionize := Value.BoolData;
OptionCountWithoutSectionNames..OptionCountWithoutSectionNames +
Ord(High(TCommentSection)) - Ord(Low(TCommentSection)) - 1:
SetSectionNames(TCommentSection(Index - PreOptionCount -
OptionCountWithoutSectionNames +
Cardinal(Ord(Succ(low(TCommentSection))))),
Value.StrData);
else
Assert(Index >= GetOptionCount); //invalid index!
raise EInvalidOption.Create('Invalid index for option supplied!');
end;
end;
{Sets the names of sections not to be recognized as sections on its own. All
these section names will not be treated as sections and the name and the
content will be just part of the previous section. Not all extractors have to
support this.
~param IgnoredNames the list of ignored section names to be set; can be nil to
just test whether the extractor supports this
~result whether this extractor supports the ignoring of sections names }
function TSectionExtractor.SetIgnoredSectionNames(
IgnoredNames: TStrings): Boolean;
begin
if Assigned(IgnoredNames) then //not just testing for support?
FIgnoredSectionNames.Assign(IgnoredNames); //set the list
Result := True; //ignored section names are supported
end;
{Returns the text as comments.
And here an inherited copy of the text:~[br]
~[inheritDoc]
~param Text the text of a comment to split in sections
~param Force whether the sectioning of the text should always be done, even
if it is disabled
~result the text as comments }
function TSectionExtractor.Sectionize(Text: String; Force: Boolean): TComment;
var Comments :TCommentSectionLists; //the comments in sections
UnknownNames :TStringList; //names of unknown sections
UnknownSections :TStringList; //comments of unknown sections
{Adds a comment of a section.
~param Section the section of the comment to add
~param Text the comment to add to the section }
procedure AddSection(Section: TCommentSection; const Text: String);
begin
if not Assigned(Comments[Section]) then //list not created, yet?
Comments[Section] := TStringList.Create; //create it
Comments[Section].Append(TrimLeftMargin(Text)); //add the text
end;
{Adds a comment of an unknown section.
~param Name the name of the unknown section
~param Text the comment of the section }
procedure AddUnknownSection(const Name: String; const Text: String);
begin
if not Assigned(UnknownNames) then //lists not created, yet?
begin
UnknownNames := TStringList.Create; //create them
UnknownSections := TStringList.Create; //create them
end;
//add comment of unknown section
UnknownSections.Insert(UnknownNames.Add(Name), TrimLeftMargin(Text));
end;
var p :PChar; //runner through the name of the section
SectionName :String; //the name of the section
Index :Integer; //index in names of sections
Section :TCommentSection; //counter to free all sections
begin
FillChar(Comments, SizeOf(Comments), Char(nil)); //clear comments
UnknownNames := nil;
UnknownSections := nil;
try
//comments should not be parsed?
if FDoNotSectionize and not Force then
//just add whole comment as the main comment
AddSection(csComment, TrimRight(Text))
else
begin
//get the first section and add it as the main comment
AddSection(csComment, TrimRight(GetCommentTillNextSection(Text)));
while Text <> '' do //while not got all sections
begin
Assert(Text[1] = FSectionSeparatorChar);
p := Pointer(Text);
Inc(p); //skip the special character
while p^ in SectionNameChars do
Inc(p); //skip the name of the section
//get the name of the section
SectionName := Copy(Text, 2, Cardinal(p) - Cardinal(Pointer(Text)) - 1);
while p^ in [#1..' '] do //skip following whitespaces
Inc(p);
//delete name of section and whitespaces
Delete(Text, 1, Cardinal(p) - Cardinal(Pointer(Text)));
Index := FSectionNames.IndexOf(SectionName); //search the name
if Index <> -1 then //known, valid section?
//add the text to the section
AddSection(TCommentSection(FSectionNames.Objects[Index]),
TrimRight(GetCommentTillNextSection(Text)))
else
//add the text with the unknown name as a section
AddUnknownSection(SectionName,
TrimRight(GetCommentTillNextSection(Text)));
end; //while Text <> ''
end; //else FDoNotSectionize and not Force
//create and return the comment
Result := TComment.Create(Comments, UnknownNames, UnknownSections);
finally
for Section := Low(Section) to High(Section) do //free all sections
Comments[Section].Free;
UnknownNames.Free;
UnknownSections.Free;
end;
end;
{Returns the text up to the beginning of the next section and removes it from
the text.
~param Comment the text to get the first section from
~result the first section of the text }
function TSectionExtractor.GetCommentTillNextSection(var Comment: String):
String;
{Checks whether the name of a section should be ignored as a section.
~param NamePointer the pointer to the beginning of the name of the section
~param Len the length of the name of the section
~result whether the section name is ignored }
function IsIgnoredSectionName(NamePointer: PChar; Len: Integer): Boolean;
var Name :String; //the name of the section
begin
SetString(Name, NamePointer, len); //get the name of the section and
Result := FIgnoredSectionNames.IndexOf(Name) <> -1; //look if it is ignored
end;
var SectionChar :Char; //the character used to separate sections
p :PChar; //runner through the string
c :Char; //each character in the string
len :Integer; //length of the first section
pname :PChar; //runner through name of section
begin
if Comment <> '' then //text not empty?
begin
SectionChar := FSectionSeparatorChar;
p := Pointer(Comment);
pname := p; //only for the compiler
repeat
//run through it until the special character
while (p^ <> #0) and //followed by a section name is found
((p^ <> SectionChar) or
not (PChar(Cardinal(p) + 1)^ in
SectionNameStartChars)) do
begin
c := p^;
Inc(p); //next character
//is a quoted special character?
if (c = SectionChar) and (p^ = SectionChar) then
Inc(p); //skip quoted character, too
end;
if p^ <> #0 then //not end of comment reached?
begin
pname := p; //skip name of the section
Inc(pname);
while pname^ in SectionNameChars do
Inc(pname);
//section name is not ended by whitespace, end of comment or
//another section?
if not (pname^ in [#0..#32, SectionChar]) then
p := pname //resume search after the name
else
//check whether the section name should be ignored
if IsIgnoredSectionName(p + 1, pname - p - 1) then
begin
p := pname; //resume search after the name
Dec(pname); //set on an "invalid" character
end;
end; //if p^ <> #0
//until end of comment reached or section name is ended by a whitespace, the
//end of the comment or a new section
until (p^ = #0) or (pname^ in [#0..#32, SectionChar]);
len := Cardinal(p) - Cardinal(Pointer(Comment)); //get length of the section
Result := Copy(Comment, 1, len); //return section text
Delete(Comment, 1, len); //and delete it
end
else
Result := ''; //just return the empty text
end;
{Adds a class of extractors of comments to the list of extractors.
~param ExtractorClass the class of extractors to add to the list }
procedure AddCommentExtractorClass(ExtractorClass: TCommentExtractorClass);
begin
if not Assigned(ExtractorClasses) then //list not initialized, yet?
ExtractorClasses := TStringList.Create; //create it
//add the extractor with its name
ExtractorClasses.AddObject(ExtractorClass.ClassName, TObject(ExtractorClass));
end;
initialization
//create list of extractors unless already created
if not Assigned(ExtractorClasses) then
ExtractorClasses := TStringList.Create;
finalization
ExtractorClasses.Free; //free the list of extractors
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -