IEnumerable <FarFile> DoInvokeDeep(ProgressBox progress, Explorer explorer, int depth) { // stop? if (Stopping || progress != null && UIUserStop()) { yield break; } ++ProcessedDirectoryCount; // progress if (progress != null && progress.ElapsedFromShow.TotalMilliseconds > 500) { var directoryPerSecond = ProcessedDirectoryCount / progress.ElapsedFromStart.TotalSeconds; progress.Activity = string.Format(null, Res.SearchActivityDeep, FoundFileCount, ProcessedDirectoryCount, directoryPerSecond); progress.ShowProgress(); } var args = new GetFilesEventArgs(ExplorerModes.Find); foreach (var file in explorer.GetFiles(args)) { // stop? if (Stopping) { break; } // process and add bool add = Directory || !file.IsDirectory; if (add && Filter != null) { add = Filter(explorer, file); } if (add) { ++FoundFileCount; yield return(new SuperFile(explorer, file)); } // skip if deep or leaf if (Depth > 0 && depth >= Depth || !file.IsDirectory) { continue; } Explorer explorer2 = SuperExplorer.ExploreSuperDirectory(explorer, ExplorerModes.Find, file); if (explorer2 == null) { continue; } foreach (var file2 in DoInvokeDeep(progress, explorer2, depth + 1)) { yield return(file2); } } }
IEnumerable <FarFile> InvokeWithProgress() { using (var progress = new ProgressBox(Res.Searching)) { progress.LineCount = 2; return(DoInvoke(progress)); } }
//! It returns immediately and then only iterates, do not try/catch in here. IEnumerable <FarFile> DoInvoke(ProgressBox progress) { FoundFileCount = 0; ProcessedDirectoryCount = 0; if (!string.IsNullOrEmpty(XFile) || !string.IsNullOrEmpty(XPath)) { return(DoInvokeXPath(progress)); } else if (Depth == 0) { return(DoInvokeWide(progress)); } else { return(DoInvokeDeep(progress, _RootExplorer, 0)); } }
IEnumerable <FarFile> DoInvokeXPath(ProgressBox progress) { // object context var objectContext = new XPathObjectContext() { Filter = this.Filter, IncrementDirectoryCount = delegate(int count) { ProcessedDirectoryCount += count; if (progress == null) { return; } var directoryPerSecond = ProcessedDirectoryCount / progress.ElapsedFromStart.TotalSeconds; progress.Activity = string.Format(null, Res.SearchActivityDeep, FoundFileCount, ProcessedDirectoryCount, directoryPerSecond); progress.ShowProgress(); }, Stopping = delegate { return(Stopping || progress != null && UIUserStop()); } }; var xsltContext = new XPathXsltContext(objectContext.NameTable); if (_XVariables != null) { foreach (var kv in _XVariables) { xsltContext.AddVariable(kv.Key, kv.Value); } } // XPath text string xpath; if (string.IsNullOrEmpty(XFile)) { xpath = XPath; } else { var input = XPathInput.ParseFile(XFile); xpath = input.Expression; foreach (var kv in input.Variables) { xsltContext.AddVariable(kv.Key, kv.Value); } } var expression = XPathExpression.Compile(xpath); if (expression.ReturnType != XPathResultType.NodeSet) { throw new InvalidOperationException("Invalid expression return type."); } expression.SetContext(xsltContext); ++ProcessedDirectoryCount; var args = new GetFilesEventArgs(ExplorerModes.Find); foreach (var file in _RootExplorer.GetFiles(args)) { // stop? if (Stopping || progress != null && UIUserStop()) //???? progress to navigator { break; } // filter out a leaf if (Filter != null && !file.IsDirectory && !Filter(_RootExplorer, file)) { continue; } var xfile = new SuperFile(_RootExplorer, file); var navigator = new XPathObjectNavigator(xfile, objectContext); var iterator = navigator.Select(expression); while (iterator.MoveNext()) { // stop? if (Stopping || progress != null && UIUserStop()) //???? progress to navigator { break; } // found file or directory, ignore anything else if (!(iterator.Current.UnderlyingObject is SuperFile currentFile)) { continue; } // filter out directory, it is already done for files if (Filter != null && currentFile.IsDirectory && (!Directory || !Filter(currentFile.Explorer, currentFile.File))) { continue; } // add yield return(currentFile); ++FoundFileCount; } } }
IEnumerable <FarFile> DoInvokeWide(ProgressBox progress) { var queue = new Queue <Explorer>(); queue.Enqueue(_RootExplorer); while (queue.Count > 0 && !Stopping) { // cancel? if (progress != null && UIUserStop()) { break; } // current var explorer = queue.Dequeue(); ++ProcessedDirectoryCount; // progress if (progress != null && progress.ElapsedFromShow.TotalMilliseconds > 500) { var directoryPerSecond = ProcessedDirectoryCount / progress.ElapsedFromStart.TotalSeconds; progress.Activity = string.Format(null, Res.SearchActivityWide, FoundFileCount, ProcessedDirectoryCount, queue.Count, directoryPerSecond); progress.ShowProgress(); } var args = new GetFilesEventArgs(ExplorerModes.Find); foreach (var file in explorer.GetFiles(args)) { // stop? if (Stopping) { break; } // process and add bool add = Directory || !file.IsDirectory; if (add && Filter != null) { add = Filter(explorer, file); } if (add) { ++FoundFileCount; yield return(new SuperFile(explorer, file)); } // skip if flat or leaf if (!Recurse || !file.IsDirectory) { continue; } Explorer explorer2 = SuperExplorer.ExploreSuperDirectory(explorer, ExplorerModes.Find, file); if (explorer2 != null) { queue.Enqueue(explorer2); } } } }