static XPathInput Parse(string[] lines) { var result = new XPathInput { Variables = new Dictionary <string, object>() }; var regex1 = new Regex(@"^declare\s+variable\s+\$(\w+)\s+(.*)"); var regex2 = new Regex(@"^external[;\s]*$"); var regex3 = new Regex(@"^:=\s*(.*?)[;\s]*$"); int i; bool comment = false; for (i = 0; i < lines.Length; ++i) { var line = lines[i].Trim(); repeat: // empty line if (line.Length == 0) { continue; } // comment if (comment) { int index = line.IndexOf(":)", StringComparison.Ordinal); if (index < 0) { continue; } line = line.Substring(index + 2).Trim(); comment = false; goto repeat; } else if (line.StartsWith("(:", StringComparison.Ordinal)) { line = line.Substring(2); comment = true; goto repeat; } var match = regex1.Match(line); if (!match.Success) { break; } var name = match.Groups[1].Value; var text = match.Groups[2].Value; match = regex2.Match(text); if (match.Success) { // prompt text = Far.Api.Input("Variable: " + name, "XPathVariable", "Input variable"); if (text == null) { result.Variables.Add(name, string.Empty); continue; } if (double.TryParse(text, out double adouble)) { result.Variables.Add(name, adouble); } else { result.Variables.Add(name, text); } continue; } match = regex3.Match(text); if (!match.Success) { throw new InvalidOperationException("declare variable: expected 'external' or ':='"); } text = match.Groups[1].Value; if (text.StartsWith("'", StringComparison.Ordinal) && text.EndsWith("'", StringComparison.Ordinal) || text.StartsWith("\"", StringComparison.Ordinal) && text.EndsWith("\"", StringComparison.Ordinal)) { result.Variables.Add(name, text.Substring(1, text.Length - 2)); } else { if (!double.TryParse(text, out double adouble)) { throw new InvalidOperationException("Not supported variable value."); } result.Variables.Add(name, adouble); } } result.Expression = string.Join(Environment.NewLine, lines, i, lines.Length - i); return(result); }
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; } } }
static XPathInput Parse(string[] lines) { var result = new XPathInput(); result.Variables = new Dictionary<string, object>(); var regex1 = new Regex(@"^declare\s+variable\s+\$(\w+)\s+(.*)"); var regex2 = new Regex(@"^external[;\s]*$"); var regex3 = new Regex(@"^:=\s*(.*?)[;\s]*$"); int i; bool comment = false; for (i = 0; i < lines.Length; ++i) { var line = lines[i].Trim(); repeat: // empty line if (line.Length == 0) continue; // comment if (comment) { int index = line.IndexOf(":)", StringComparison.Ordinal); if (index < 0) continue; line = line.Substring(index + 2).Trim(); comment = false; goto repeat; } else if (line.StartsWith("(:", StringComparison.Ordinal)) { line = line.Substring(2); comment = true; goto repeat; } var match = regex1.Match(line); if (!match.Success) break; var name = match.Groups[1].Value; var text = match.Groups[2].Value; match = regex2.Match(text); if (match.Success) { // prompt text = Far.Api.Input("Variable: " + name, "XPathVariable", "Input variable"); if (text == null) { result.Variables.Add(name, string.Empty); continue; } double adouble; if (double.TryParse(text, out adouble)) result.Variables.Add(name, adouble); else result.Variables.Add(name, text); continue; } match = regex3.Match(text); if (!match.Success) throw new InvalidOperationException("declare variable: expected 'external' or ':='"); text = match.Groups[1].Value; if (text.StartsWith("'", StringComparison.Ordinal) && text.EndsWith("'", StringComparison.Ordinal) || text.StartsWith("\"", StringComparison.Ordinal) && text.EndsWith("\"", StringComparison.Ordinal)) { result.Variables.Add(name, text.Substring(1, text.Length - 2)); } else { double adouble; if (!double.TryParse(text, out adouble)) throw new InvalidOperationException("Not supported variable value."); result.Variables.Add(name, adouble); } } result.Expression = string.Join(Environment.NewLine, lines, i, lines.Length - i); return result; }