private static Match[] Evaluate(HtmlDocument document, Control tb, ListBox lb, Control hb, ToolStripItem status, IEnumerable<Match> oldMatches, RichTextBox rtb) { var input = tb.Text.Trim(); tb.ForeColor = SystemColors.WindowText; var elements = new HtmlNode[0]; if (string.IsNullOrEmpty(input)) { status.Text = "Ready"; hb.Text = null; } else { try { // // Simple way to query for elements: // // nodes = document.DocumentNode.QuerySelectorAll(input).ToArray(); // // However, we want to generate the human readable text and // the element selector in a single pass so go the bare metal way // here to make all the parties to talk to each other. // var generator = new SelectorGenerator<HtmlNode>(new HtmlNodeOps()); var helper = new HumanReadableSelectorGenerator(); Parser.Parse(input, new SelectorGeneratorTee(generator, helper)); if (document != null) elements = generator.Selector(Enumerable.Repeat(document.DocumentNode, 1)).ToArray(); hb.Text = helper.Text; status.Text = "Matches: " + elements.Length.ToString("N0"); } catch (FormatException e) { tb.ForeColor = Color.FromKnownColor(KnownColor.Red); status.Text = "Error: " + e.Message; hb.Text = "Oops! " + e.Message; } } if (oldMatches != null) Highlight(rtb, oldMatches, null, SystemColors.Info, null); lb.BeginUpdate(); try { lb.Items.Clear(); if (!elements.Any()) return new Match[0]; var html = rtb.Text; var matches = new List<Match>(elements.Length); foreach (var element in elements) { var index = rtb.GetFirstCharIndexFromLine(element.Line - 1) + element.LinePosition - 1; var match = _tagExpression.Match(html, index); if (match.Success) matches.Add(match); } Highlight(rtb, matches, null, Color.Yellow, null); lb.Items.AddRange(elements.Select(n => n.GetBeginTagString()).ToArray()); return matches.ToArray(); } finally { lb.EndUpdate(); } }