IDE: find in files: search in multiple directories

git-svn-id: trunk@45992 -
This commit is contained in:
mattias 2014-07-30 12:07:54 +00:00
parent 3e8d8b891e
commit fc22ff99e3
6 changed files with 164 additions and 117 deletions

View File

@ -12,7 +12,7 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
Constraints.MinWidth = 400
OnClose = FormClose
OnCreate = FormCreate
LCLVersion = '1.1'
LCLVersion = '1.3'
object OptionsCheckGroupBox: TCheckGroup
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = ReplaceTextComboBox
@ -21,7 +21,7 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideRight.Side = asrBottom
Left = 6
Height = 83
Top = 76
Top = 72
Width = 449
Anchors = [akTop, akLeft, akRight]
AutoFill = True
@ -38,8 +38,8 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 2
ClientHeight = 62
ClientWidth = 441
ClientHeight = 66
ClientWidth = 445
Columns = 2
Items.Strings = (
'Case sensitive'
@ -60,7 +60,7 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideRight.Side = asrBottom
Left = 6
Height = 83
Top = 165
Top = 161
Width = 449
Anchors = [akTop, akLeft, akRight]
AutoFill = True
@ -77,8 +77,8 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 2
ClientHeight = 62
ClientWidth = 441
ClientHeight = 66
ClientWidth = 445
Columns = 2
ItemIndex = 1
Items.Strings = (
@ -97,75 +97,77 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 6
Height = 131
Top = 254
Height = 125
Top = 250
Width = 449
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Around = 6
Caption = 'Directory Options'
ClientHeight = 110
ClientWidth = 441
ClientHeight = 108
ClientWidth = 445
Enabled = False
TabOrder = 5
object DirectoryLabel: TLabel
object DirectoriesLabel: TLabel
AnchorSideLeft.Control = DirectoryOptionsGroupBox
AnchorSideTop.Control = DirectoryComboBox
AnchorSideTop.Control = DirectoriesComboBox
AnchorSideTop.Side = asrCenter
Left = 6
Height = 17
Height = 15
Top = 12
Width = 61
Width = 65
BorderSpacing.Left = 6
Caption = 'Directory:'
FocusControl = DirectoryComboBox
Caption = 'Directories:'
FocusControl = DirectoriesComboBox
ParentColor = False
end
object FileMaskLabel: TLabel
AnchorSideLeft.Control = DirectoryOptionsGroupBox
AnchorSideTop.Control = DirectoryComboBox
AnchorSideTop.Control = DirectoriesComboBox
AnchorSideTop.Side = asrBottom
Left = 6
Height = 17
Top = 47
Width = 59
Height = 15
Top = 45
Width = 49
BorderSpacing.Left = 6
BorderSpacing.Top = 12
Caption = 'File mask'
FocusControl = FileMaskComboBox
ParentColor = False
end
object DirectoryComboBox: TComboBox
AnchorSideLeft.Control = DirectoryLabel
object DirectoriesComboBox: TComboBox
AnchorSideLeft.Control = DirectoriesLabel
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = DirectoryOptionsGroupBox
AnchorSideRight.Control = DirectoryBrowse
Left = 73
Height = 29
AnchorSideRight.Control = DirectoriesBrowse
Left = 77
Height = 27
Top = 6
Width = 330
Width = 335
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Top = 6
BorderSpacing.Right = 6
ItemHeight = 0
ParentShowHint = False
ShowHint = True
TabOrder = 0
end
object DirectoryBrowse: TBitBtn
object DirectoriesBrowse: TBitBtn
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = DirectoryComboBox
AnchorSideTop.Control = DirectoriesComboBox
AnchorSideRight.Control = DirectoryOptionsGroupBox
AnchorSideRight.Side = asrBottom
Left = 409
Height = 28
Left = 418
Height = 27
Top = 6
Width = 26
Width = 21
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Right = 6
Caption = '...'
Layout = blGlyphTop
OnClick = DirectoryBrowseClick
OnClick = DirectoriesBrowseClick
TabOrder = 1
end
object FileMaskComboBox: TComboBox
@ -173,12 +175,12 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = FileMaskLabel
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = DirectoryComboBox
AnchorSideRight.Control = DirectoriesComboBox
AnchorSideRight.Side = asrBottom
Left = 71
Height = 29
Top = 41
Width = 332
Left = 61
Height = 27
Top = 39
Width = 351
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
ItemHeight = 0
@ -190,9 +192,9 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideTop.Control = FileMaskComboBox
AnchorSideTop.Side = asrBottom
Left = 6
Height = 22
Top = 82
Width = 170
Height = 24
Top = 78
Width = 151
BorderSpacing.Left = 6
BorderSpacing.Top = 12
BorderSpacing.Bottom = 6
@ -204,8 +206,8 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
end
object ButtonPanel1: TButtonPanel
Left = 6
Height = 33
Top = 398
Height = 28
Top = 403
Width = 449
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
@ -229,10 +231,10 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 88
Height = 29
Top = 41
Width = 367
Left = 82
Height = 27
Top = 39
Width = 373
Anchors = [akTop, akLeft, akRight]
AutoComplete = True
AutoCompleteText = [cbactEnabled, cbactEndOfLineComplete, cbactRetainPrefixCase, cbactSearchAscending]
@ -249,9 +251,9 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideTop.Control = ReplaceTextComboBox
AnchorSideTop.Side = asrCenter
Left = 6
Height = 22
Top = 44
Width = 76
Height = 24
Top = 40
Width = 70
BorderSpacing.Left = 6
Caption = 'Replace'
Enabled = False
@ -263,9 +265,9 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideTop.Control = TextToFindComboBox
AnchorSideTop.Side = asrCenter
Left = 6
Height = 17
Height = 15
Top = 12
Width = 75
Width = 69
BorderSpacing.Left = 6
Caption = 'Text To Find:'
ParentColor = False
@ -276,10 +278,10 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
AnchorSideTop.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 87
Height = 29
Left = 81
Height = 27
Top = 6
Width = 368
Width = 374
Anchors = [akTop, akLeft, akRight]
AutoComplete = True
AutoCompleteText = [cbactEnabled, cbactEndOfLineComplete, cbactRetainPrefixCase, cbactSearchAscending]
@ -292,7 +294,7 @@ object LazFindInFilesDialog: TLazFindInFilesDialog
object SelectDirectoryDialog: TSelectDirectoryDialog
FilterIndex = 0
Options = [ofFileMustExist, ofEnableSizing, ofViewDetail]
left = 260
top = 215
left = 180
top = 70
end
end

View File

@ -17,10 +17,14 @@ unit FindInFilesDlg;
interface
uses
Classes, SysUtils, LCLProc, LCLIntf, Controls, StdCtrls, Forms, Buttons,
ExtCtrls, FileProcs, LazarusIDEStrConsts, Dialogs, SynEditTypes, ButtonPanel,
Classes, SysUtils,
FileProcs,
LCLProc, LCLIntf, Controls, StdCtrls, Forms, Buttons, ExtCtrls, Dialogs,
ButtonPanel,
SynEditTypes, SynEdit,
MacroIntf, IDEWindowIntf, SrcEditorIntf, IDEHelpIntf, IDEDialogs,
InputHistory, EditorOptions, SearchFrm, Project, SynEdit, SearchResultView;
LazarusIDEStrConsts, InputHistory, EditorOptions, Project, IDEProcs,
SearchFrm, SearchResultView;
type
{ TLazFindInFilesDialog }
@ -31,9 +35,9 @@ type
ReplaceTextComboBox: TComboBox;
IncludeSubDirsCheckBox: TCheckBox;
FileMaskComboBox: TComboBox;
DirectoryBrowse: TBitBtn;
DirectoryComboBox: TComboBox;
DirectoryLabel: TLabel;
DirectoriesBrowse: TBitBtn;
DirectoriesComboBox: TComboBox;
DirectoriesLabel: TLabel;
FileMaskLabel: TLabel;
DirectoryOptionsGroupBox: TGroupBox;
OptionsCheckGroupBox: TCheckGroup;
@ -41,7 +45,7 @@ type
TextToFindComboBox: TComboBox;
TextToFindLabel: TLabel;
WhereRadioGroup: TRadioGroup;
procedure DirectoryBrowseClick(Sender: TObject);
procedure DirectoriesBrowseClick(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure HelpButtonClick(Sender: TObject);
@ -65,12 +69,13 @@ type
property ReplaceText: string read GetReplaceText write SetReplaceText;
property SynSearchOptions: TSynSearchOptions read GetSynOptions
write SetSynOptions;
function GetBaseDirectory: string;
procedure LoadHistory;
procedure SaveHistory;
procedure FindInFilesPerDialog(AProject: TProject);
procedure InitFromLazSearch(Sender: TObject);
procedure FindInFiles(AProject: TProject; const AFindText: string);
function GetResolvedDirectory: string;
function GetResolvedDirectories: string;
end;
function FindInFilesDialog: TLazFindInFilesDialog;
@ -119,18 +124,28 @@ begin
DirectoryOptionsGroupBox.Enabled := (WhereRadioGroup.ItemIndex = ItemIndDirectories)
end;
procedure TLazFindInFilesDialog.DirectoryBrowseClick(Sender: TObject);
procedure TLazFindInFilesDialog.DirectoriesBrowseClick(Sender: TObject);
var
Dir: String;
OldDirs: String;
p: Integer;
begin
InitIDEFileDialog(SelectDirectoryDialog);
Dir:=GetResolvedDirectory;
if DirectoryExistsUTF8(Dir) then
// use the first directory as initialdir for the dialog
OldDirs:=GetResolvedDirectories;
p:=1;
repeat
Dir:=GetNextDirectoryInSearchPath(OldDirs,p);
if Dir='' then break;
if DirectoryExistsUTF8(Dir) then break;
until false;
if Dir<>'' then
SelectDirectoryDialog.InitialDir := Dir
else
SelectDirectoryDialog.InitialDir := GetCurrentDirUTF8;
SelectDirectoryDialog.InitialDir := GetBaseDirectory;
if SelectDirectoryDialog.Execute then
DirectoryComboBox.Text := AppendPathDelim(TrimFilename(SelectDirectoryDialog.FileName));
DirectoriesComboBox.Text := AppendPathDelim(TrimFilename(SelectDirectoryDialog.FileName));
StoreIDEFileDialog(SelectDirectoryDialog);
end;
@ -160,7 +175,8 @@ begin
WhereRadioGroup.Items[ItemIndActiveFile] := lisFindFilesearchInActiveFile;
DirectoryOptionsGroupBox.Caption := lisFindFileDirectoryOptions;
DirectoryLabel.Caption := lisFindFileDirectory;
DirectoriesComboBox.Hint:=lisMultipleDirectoriesAreSeparatedWithSemicolons;
DirectoriesLabel.Caption := lisFindFileDirectory;
FileMaskLabel.Caption := lisFindFileFileMask;
IncludeSubDirsCheckBox.Caption := lisFindFileIncludeSubDirectories;
@ -185,14 +201,20 @@ end;
procedure TLazFindInFilesDialog.OKButtonClick(Sender : TObject);
var
Dir: String;
p: Integer;
begin
Dir:=GetResolvedDirectory;
if (WhereRadioGroup.ItemIndex=ItemIndDirectories) and not DirectoryExistsUTF8(Dir) then
if (WhereRadioGroup.ItemIndex=ItemIndDirectories) then
begin
IDEMessageDialog(lisEnvOptDlgDirectoryNotFound,
Format(dlgSeachDirectoryNotFound,[Dir]),
mtWarning, [mbOk]);
ModalResult:=mrNone;
Dir:=GetResolvedDirectories;
p:=1;
Dir:=GetNextDirectoryInSearchPath(Dir,p);
if not DirectoryExistsUTF8(Dir) then
begin
IDEMessageDialog(lisEnvOptDlgDirectoryNotFound,
Format(dlgSeachDirectoryNotFound,[Dir]),
mtWarning, [mbOk]);
ModalResult:=mrNone;
end;
end
end;
@ -272,6 +294,15 @@ begin
ButtonPanel1.OKButton.Caption := lisBtnFind;
end;
function TLazFindInFilesDialog.GetBaseDirectory: string;
begin
Result:='';
if Project1<>nil then
Result:=Project1.ProjectDirectory;
if Result='' then
Result:=GetCurrentDirUTF8;
end;
procedure TLazFindInFilesDialog.LoadHistory;
procedure AssignToComboBox(AComboBox: TComboBox; Strings: TStrings);
@ -319,11 +350,11 @@ begin
end;
end;
// show last used directories and directory of current file
AssignToComboBox(DirectoryComboBox, InputHistories.FindInFilesPathHistory);
AssignToComboBox(DirectoriesComboBox, InputHistories.FindInFilesPathHistory);
if (SrcEdit<>nil) and (FilenameIsAbsolute(SrcEdit.FileName)) then
AddFileToComboBox(DirectoryComboBox, ExtractFilePath(SrcEdit.FileName));
if DirectoryComboBox.Items.Count>0 then
DirectoryComboBox.Text:=DirectoryComboBox.Items[0];
AddFileToComboBox(DirectoriesComboBox, ExtractFilePath(SrcEdit.FileName));
if DirectoriesComboBox.Items.Count>0 then
DirectoriesComboBox.Text:=DirectoriesComboBox.Items[0];
// show last used file masks
AssignToComboBox(FileMaskComboBox, InputHistories.FindInFilesMaskHistory);
Options := InputHistories.FindInFilesSearchOptions;
@ -334,7 +365,7 @@ var
Dir: String;
begin
InputHistories.AddToFindHistory(FindText);
Dir:=AppendPathDelim(TrimFilename(DirectoryComboBox.Text));
Dir:=AppendPathDelim(TrimFilename(DirectoriesComboBox.Text));
if Dir<>'' then
InputHistories.AddToFindInFilesPathHistory(Dir);
InputHistories.AddToFindInFilesMaskHistory(FileMaskComboBox.Text);
@ -369,9 +400,9 @@ procedure TLazFindInFilesDialog.InitFromLazSearch(Sender: TObject);
var
Dir: String;
begin
Dir:=AppendPathDelim(TrimFilename(TLazSearch(Sender).SearchDirectory));
Dir:=AppendPathDelim(TrimFilename(TLazSearch(Sender).SearchDirectories));
if Dir<>'' then
DirectoryComboBox.Text:= Dir;
DirectoriesComboBox.Text:= Dir;
Options:= TLazSearch(Sender).SearchOptions;
FileMaskComboBox.Text:= TLazSearch(Sender).SearchMask;
end;
@ -396,11 +427,11 @@ begin
SearchForm:= TSearchProgressForm.Create(SearchResultsView);
with SearchForm do begin
SearchOptions := self.Options;
SearchText := self.FindText;
ReplaceText := self.ReplaceText;
SearchMask := self.FileMaskComboBox.Text;
SearchDirectory := self.GetResolvedDirectory;
SearchOptions := self.Options;
SearchText := self.FindText;
ReplaceText := self.ReplaceText;
SearchMask := self.FileMaskComboBox.Text;
SearchDirectories := self.GetResolvedDirectories;
end;
try
@ -419,11 +450,11 @@ begin
end;
end;
function TLazFindInFilesDialog.GetResolvedDirectory: string;
function TLazFindInFilesDialog.GetResolvedDirectories: string;
begin
Result:=DirectoryComboBox.Text;
Result:=DirectoriesComboBox.Text;
IDEMacros.SubstituteMacros(Result);
Result:=TrimAndExpandDirectory(Result);
Result:=TrimSearchPath(Result,GetBaseDirectory,true,true);
end;
end.

View File

@ -123,7 +123,7 @@ function FindProgram(const Programname, BaseDirectory: string;
// search paths
function TrimSearchPath(const SearchPath, BaseDirectory: string;
DeleteDoubles: boolean = false): string;
DeleteDoubles: boolean = false; ExpandPaths: boolean = false): string;
function MergeSearchPaths(const OldSearchPath, AddSearchPath: string): string;
procedure MergeSearchPaths(SearchPath: TStrings; const AddSearchPath: string);
function RemoveSearchPaths(const SearchPath, RemoveSearchPath: string): string;
@ -1363,7 +1363,7 @@ end;
- removes doubles
-------------------------------------------------------------------------------}
function TrimSearchPath(const SearchPath, BaseDirectory: string;
DeleteDoubles: boolean): string;
DeleteDoubles: boolean; ExpandPaths: boolean): string;
var
CurPath: String;
EndPos: Integer;
@ -1386,7 +1386,9 @@ begin
CurPath:=copy(SearchPath,StartPos,EndPos-StartPos);
if CurPath<>'' then begin
// non empty path => expand, trim and normalize
if (BaseDir<>'') and (not FilenameIsAbsolute(CurPath)) then
if ExpandPaths then
CurPath:=TrimAndExpandDirectory(CurPath,BaseDir)
else if (BaseDir<>'') and (not FilenameIsAbsolute(CurPath)) then
CurPath:=BaseDir+CurPath;
CurPath:=ChompPathDelim(TrimFilename(CurPath));
if CurPath='' then CurPath:='.';

View File

@ -3748,6 +3748,8 @@ resourcestring
lisFindFilesearchInDirectories = 'search in &directories';
lisFindFileDirectoryOptions = 'Directory options';
lisFindFileDirectory = 'D&irectory';
lisMultipleDirectoriesAreSeparatedWithSemicolons = 'Multiple directories are'
+' separated with semicolons';
lisFindFileFileMask = 'Fi&le mask';
lisFindFileIncludeSubDirectories = 'Include &sub directories';
lisFindFileOnlyTextFiles = 'Only text files';

View File

@ -39,7 +39,7 @@ uses
// IDEIntf
IDEWindowIntf, LazIDEIntf, SrcEditorIntf, IDEDialogs, MainIntf,
// ide
LazarusIDEStrConsts, InputHistory, SearchResultView, Project;
LazarusIDEStrConsts, InputHistory, IDEProcs, SearchResultView, Project;
type
@ -77,14 +77,14 @@ type
fSearchFileList: TStringList;
fSearchFiles: boolean;
fSearchFor: String;
fTheDirectory: string;
fDirectories: string;
fSearchOpen: boolean;
fSearchActive: boolean;
fSearchProject: boolean;
fAborting: boolean;
fLastUpdateProgress: DWORD;
fWasActive: boolean;
procedure DoFindInFiles(ADirectory: string);
procedure DoFindInFiles(ADirectories: string);
procedure DoFindInSearchList;
procedure SetResultsList(const AValue: TStrings);
procedure UpdateMatches;
@ -102,7 +102,7 @@ type
procedure DoSearchDir;
procedure DoSearchProject(AProject: TProject);
public
property SearchDirectory: string read fTheDirectory write fTheDirectory;
property SearchDirectories: string read fDirectories write fDirectories;
property SearchText: string read fSearchFor write fSearchFor;
property ReplaceText: string read FReplaceText write FReplaceText;
property SearchOptions: TLazFindInFileSearchOptions read GetOptions
@ -761,7 +761,7 @@ begin
end;
try
if fSearchFiles then
DoFindInFiles(fTheDirectory);
DoFindInFiles(fDirectories);
if fSearchProject or fSearchOpen or fSearchActive then
DoFindInSearchList;
if Assigned(fResultsList) then begin
@ -849,19 +849,29 @@ end;
{ TSearchProgressForm }
procedure TSearchProgressForm.DoFindInFiles(ADirectory: string);
procedure TSearchProgressForm.DoFindInFiles(ADirectories: string);
var
Searcher: TLazFileSearcher;
SearchPath: String;
p: Integer;
Dir: String;
begin
//if we have a list and a valid directory
if (DirPathExists(ADirectory)) then
begin
Searcher := TLazFileSearcher.Create(Self);
try
Searcher.Search(ADirectory, FMask, FRecursive);
finally
Searcher.Free;
end;
// if we have a list and a valid directory
SearchPath:='';
p:=1;
repeat
Dir:=GetNextDirectoryInSearchPath(ADirectories,p);
if Dir='' then break;
if DirPathExists(Dir) then
SearchPath:=MergeSearchPaths(SearchPath,Dir);
until false;
if SearchPath='' then
exit;
Searcher := TLazFileSearcher.Create(Self);
try
Searcher.Search(SearchPath, FMask, FRecursive);
finally
Searcher.Free;
end;
end;
@ -953,7 +963,7 @@ begin
Cnt:= 0;
LazarusIDE.DoShowSearchResultsView(False);
ListPage:=SearchResultsView.AddSearch(SearchText,SearchText,
ReplaceText,SearchDirectory,SearchMask,SearchOptions);
ReplaceText,SearchDirectories,SearchMask,SearchOptions);
try
(* BeginUpdate prevents ListPage from being closed,
other pages can still be closed or inserted, so PageIndex can change *)

View File

@ -75,15 +75,15 @@ type
FReplaceText: string;
fSearchString: string;
fSearchOptions: TLazFindInFileSearchOptions;
fSearchDirectory: string;
fSearchDirectories: string;
fSearchMask: string;
public
property SearchString: string read fSearchString write fSearchString;
property ReplaceText: string read FReplaceText write FReplaceText;
property SearchOptions: TLazFindInFileSearchOptions read fSearchOptions
write fSearchOptions;
property SearchDirectory: string read fSearchDirectory
write fSearchDirectory;
property SearchDirectories: string read fSearchDirectories
write fSearchDirectories;
property SearchMask: string read fSearchMask write fSearchMask;
end;//TLazSearch
@ -188,7 +188,7 @@ type
function AddSearch(const ResultsName: string;
const SearchText: string;
const ReplaceText: string;
const ADirectory: string;
const ADirectories: string;
const AMask: string;
const TheOptions: TLazFindInFileSearchOptions): TTabSheet;
function GetSourcePositon: TPoint;
@ -709,7 +709,7 @@ end;
function TSearchResultsView.AddSearch(const ResultsName: string;
const SearchText: string;
const ReplaceText: string;
const ADirectory: string;
const ADirectories: string;
const AMask: string;
const TheOptions: TLazFindInFileSearchOptions): TTabSheet;
var
@ -751,7 +751,7 @@ begin
if SearchObj<>nil then begin
SearchObj.SearchString:= SearchText;
SearchObj.ReplaceText := ReplaceText;
SearchObj.SearchDirectory:= ADirectory;
SearchObj.SearchDirectories:= ADirectories;
SearchObj.SearchMask:= AMask;
SearchObj.SearchOptions:= TheOptions;
end;