MG: regular expressions for search

git-svn-id: trunk@327 -
This commit is contained in:
lazarus 2001-08-06 08:00:44 +00:00
parent 229fdb1bee
commit 1f8bda0727
3 changed files with 133 additions and 33 deletions

View File

@ -128,7 +128,8 @@ const
type
TSynSearchOption = (ssoMatchCase, ssoWholeWord, ssoBackwards,
ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt);
ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt
{$IFDEF SYN_LAZARUS}, ssoRegExpr, ssoRegExprMultiLine{$ENDIF});
TSynSearchOptions = set of TSynSearchOption;
TSynReplaceAction = (raCancel, raSkip, raReplace, raReplaceAll);
@ -5777,8 +5778,12 @@ begin
fTSearch.Sensitive := ssoMatchCase in AOptions;
fTSearch.Whole := ssoWholeWord in AOptions;
fTSearch.Pattern := ASearch;
fTSearch.RegularExpressions := ssoRegExpr in AOptions;
fTSearch.RegExprSingleLine := not (ssoRegExprMultiLine in AOptions);
// search while the current search position is inside of the search range
{$IFNDEF SYN_LAZARUS}
nSearchLen := Length(ASearch);
{$ENDIF}
nReplaceLen := Length(AReplace);
if bReplaceAll then IncPaintLock;
try
@ -5788,6 +5793,9 @@ begin
// Operate on all results in this line.
while nInLine > 0 do begin
nFound := fTSearch.Results[n];
{$IFDEF SYN_LAZARUS}
nSearchLen := fTSearch.ResultLengths[n];
{$ENDIF}
if bBackward then Dec(n) else Inc(n);
Dec(nInLine);
// Is the search result entirely in the search range?

View File

@ -42,7 +42,8 @@ unit SynEditSearch;
interface
uses
Classes;
Classes
{$IFDEF SYN_LAZARUS}, RegExpr{$ENDIF};
procedure MakeCompTable(Sensitive: boolean);
procedure MakeDelimiterTable;
@ -63,6 +64,16 @@ type
fWhole: Boolean;
fResults: TList;
fShiftInitialized: boolean;
{$IFDEF SYN_LAZARUS}
FoundLen: integer;
RegExprEngine : TRegExprEngine;
fRegExpr: Boolean;
fRegExprFlags: TRegExprFlags;
fResultLens: TList;
fRegExprSingleLine: boolean;
function GetResultLen(Index: integer): integer;
procedure SetRegExpr(const NewValue: boolean);
{$ENDIF}
function GetFinished: Boolean;
function GetResult(Index: integer): integer;
function GetResultCount: integer;
@ -85,6 +96,12 @@ type
property ResultCount: integer read GetResultCount;
property Sensitive: Boolean read fSensitive write SetSensitive;
property Whole: Boolean read fWhole write fWhole;
{$IFDEF SYN_LAZARUS}
property RegularExpressions: Boolean read fRegExpr write SetRegExpr;
property ResultLengths[Index: integer]: integer read GetResultLen;
property RegExprSingleLine: Boolean
read fRegExprSingleLine write fRegExprSingleLine;
{$ENDIF}
end;
implementation
@ -102,12 +119,6 @@ var
CompTable: array[#0..#255] of Byte;
DelimTable: array[#0..#255] of boolean;
constructor TSynEditSearch.Create;
begin
inherited Create;
fResults := TList.Create;
end;
procedure MakeCompTable(Sensitive: Boolean);
var
I: Char;
@ -134,6 +145,18 @@ begin
for c := #0 to #255 do DelimTable[c] := not IsCharAlphaNumeric(c);
end;
constructor TSynEditSearch.Create;
begin
inherited Create;
fResults := TList.Create;
{$IFDEF SYN_LAZARUS}
fRegExpr:=false;
fResultLens := TList.Create;
fRegExprSingleLine:=true;
FoundLen:=0;
{$ENDIF}
end;
{ TSynEditSearch }
function TSynEditSearch.GetFinished: Boolean;
@ -200,43 +223,64 @@ var
J: PChar;
begin
Result := 0;
inc(Run, PatLen);
while Run < TheEnd do
begin
if CompTable[Pat[Patlen]] <> CompTable[Run^] then
inc(Run, Shift[CompTable[(Run + 1)^]])
else
{$IFDEF SYN_LAZARUS}
if not fRegExpr then begin
{$ENDIF}
inc(Run, PatLen);
FoundLen:=PatLen;
while Run < TheEnd do
begin
J := Run - PatLen + 1;
I := 1;
while CompTable[Pat[I]] = CompTable[J^] do
if CompTable[Pat[Patlen]] <> CompTable[Run^] then
inc(Run, Shift[CompTable[(Run + 1)^]])
else
begin
if I = PatLen then
J := Run - PatLen + 1;
I := 1;
while CompTable[Pat[I]] = CompTable[J^] do
begin
Case fWhole of
True: if not TestWholeWord then break;
if I = PatLen then
begin
Case fWhole of
True: if not TestWholeWord then break;
end;
inc(fCount);
Result := Run - Origin - Patlen + 2;
exit;
end;
inc(fCount);
Result := Run - Origin - Patlen + 2;
exit;
inc(I);
inc(J);
end;
inc(I);
inc(J);
end;
{begin} //mh 2000-08-29
// inc(Run, Look_At + Shift[CompTable[(Run + Look_at)^]] - 1);
Inc(Run, Look_At);
if Run >= TheEnd then
break;
Inc(Run, Shift[CompTable[Run^]] - 1);
// inc(Run, Look_At + Shift[CompTable[(Run + Look_at)^]] - 1);
Inc(Run, Look_At);
if Run >= TheEnd then
break;
Inc(Run, Shift[CompTable[Run^]] - 1);
{end} //mh 2000-08-29
end;
end;
{$IFDEF SYN_LAZARUS}
end else begin
// regular expressions
inc(Run);
if not RegExprPos(RegExprEngine,Run,Result,FoundLen) then begin
Run:=TheEnd;
Result:=0;
end else begin
inc(Run,Result);
Result:=Run-Origin+1;
end;
{$ENDIF}
end;
end;
destructor TSynEditSearch.Destroy;
begin
fResults.Free;
{$IFDEF SYN_LAZARUS}
DestroyRegExprEngine(RegExprEngine);
fResultLens.Free;
{$ENDIF}
inherited Destroy;
end;
@ -252,10 +296,15 @@ end;
procedure TSynEditSearch.SetSensitive(const Value: Boolean);
begin
if fSensitive <> Value then begin
writeln('A');
fSensitive := Value;
MakeCompTable(Value);
fShiftInitialized := FALSE;
{$IFDEF SYN_LAZARUS}
if fSensitive then
Exclude(fRegExprFlags,REF_CaseInsensitive)
else
Include(fRegExprFlags,REF_CaseInsensitive);
{$ENDIF}
end;
end;
@ -267,10 +316,16 @@ begin
InitShiftTable;
// never shrink Capacity
fResults.Count := 0;
{$IFDEF SYN_LAZARUS}
if fRegExpr then fResultLens.Count := 0;
{$ENDIF}
Found := FindFirst(NewText);
while Found > 0 do
begin
fResults.Add(pointer(Found));
{$IFDEF SYN_LAZARUS}
if fRegExpr then fResultLens.Add(pointer(FoundLen));
{$ENDIF}
Found := Next;
end;
Result := fResults.Count;
@ -280,6 +335,24 @@ function TSynEditSearch.FindFirst(const NewText: string): Integer;
begin
Result := 0;
fTextLen := Length(NewText);
{$IFDEF SYN_LAZARUS}
if fRegExpr then begin
DestroyRegExprEngine(RegExprEngine);
if fSensitive then
Exclude(fRegExprFlags,REF_CaseInsensitive)
else
Include(fRegExprFlags,REF_CaseInsensitive);
if fRegExprSingleLine then begin
Include(fRegExprFlags,REF_SingleLine);
Exclude(fRegExprFlags,REF_MultiLine);
end else begin
Exclude(fRegExprFlags,REF_SingleLine);
Include(fRegExprFlags,REF_MultiLine);
end;
RegExprEngine:=GenerateRegExprEngine(PChar(Pat+#0),fRegExprFlags);
PatLen:=length(Pat);
end;
{$ENDIF}
if fTextLen >= PatLen then
begin
Origin := PChar(NewText);
@ -289,9 +362,27 @@ begin
end;
end;
{$IFDEF SYN_LAZARUS}
function TSynEditSearch.GetResultLen(Index: integer): integer;
begin
if (Index>=0) and (Index<fResultLens.Count) then
Result:=Integer(fResultLens[Index])
else
Result:=FoundLen;
end;
procedure TSynEditSearch.SetRegExpr(const NewValue: boolean);
begin
if NewValue=fRegExpr then exit;
fRegExpr:=NewValue;
end;
{$ENDIF}
initialization
CompTableSensitive := True; // force the table initialization
MakeCompTable(False);
MakeDelimiterTable;
end.

View File

@ -175,7 +175,6 @@ begin
Width:=135;
Height:=17;
Caption:='Regular Expressions';
Enabled:=false;
Show;
end;
@ -323,6 +322,7 @@ procedure TLazFindReplaceDialog.SetOptions(NewOptions:TSynSearchOptions);
begin
CaseSensitiveCheckBox.Checked:=ssoMatchCase in NewOptions;
WholeWordsOnlyCheckBox.Checked:=ssoWholeWord in NewOptions;
RegularExpressionsCheckBox.Checked:=ssoRegExpr in NewOptions;
PromptOnReplaceCheckBox.Checked:=ssoPrompt in NewOptions;
if ssoEntireScope in NewOptions
then OriginRadioGroup.ItemIndex:=1
@ -351,6 +351,7 @@ begin
Result:=[];
if CaseSensitiveCheckBox.Checked then Include(Result,ssoMatchCase);
if WholeWordsOnlyCheckBox.Checked then Include(Result,ssoWholeWord);
if RegularExpressionsCheckBox.Checked then Include(Result,ssoRegExpr);
if PromptOnReplaceCheckBox.Checked then Include(Result,ssoPrompt);
if OriginRadioGroup.ItemIndex=1 then Include(Result,ssoEntireScope);
if ScopeRadioGroup.ItemIndex=1 then include(Result,ssoSelectedOnly);