我希望运行一个RegEx搜索,在编辑器窗口中找到所有出现的某些关键字,然后绘制一些装饰品并为它们添加一些标签。
有没有办法在ITextViewLine
上运行RegEx。
这就是我的调用函数的外观:
private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
foreach (ITextViewLine line in e.NewOrReformattedLines)
{
this.CreateVisuals(line);
}
}
private void CreateVisuals(ITextViewLine line)
{
IWpfTextViewLineCollection textViewLines = _wpfTextView.TextViewLines;
// Run RegEx match here and do some stuff for all matches
}
根据@stribizhev的建议,我尝试使用FormattedSpan
,如下所示:
private void CreateVisuals(ITextViewLine line)
{
var textViewLines = _wpfTextView.TextViewLines;
var snapshot = textViewLines.FormattedSpan;
var text = snapshot.ToString();
var todoRegex = new Regex(@"\/\/\s*TODO\b");
var match = todoRegex.Match(text);
if (match.Success)
{
int matchStart = line.Start.Position + match.Index;
var span = new SnapshotSpan(_wpfTextView.TextSnapshot, Span.FromBounds(matchStart, matchStart + match.Length));
DrawAdornment(textViewLines, span);
}
}
但这会导致调用DrawAdornment时NullReference
告诉我span
未设置。
此外,通过在CreateVisuals
函数的所有行上放置断点,我发现仅当包含TODO
的行滚出视图或成为视口中的第一行时突出显示才会开始。
我尝试的输入是:
using System;
public class Class1
{
public Class1()
{
// TODO: It's a good thing to have todos
}
}
代码有时可以放置装饰品,但它们会略微向右移动并出现在三个不同的行上。
答案 0 :(得分:3)
我终于开始工作了。有两种方法可以做到。
我的方式(更简单):
private void CreateVisuals()
{
var textViewLines = _wpfTextView.TextViewLines;
var text = textViewLines.FormattedSpan.Snapshot.GetText();
var todoRegex = new Regex(@"\/\/\s*TODO\b");
var match = todoRegex.Match(text);
while (match.Success)
{
var matchStart = match.Index;
var span = new SnapshotSpan(_wpfTextView.TextSnapshot, Span.FromBounds(matchStart, matchStart + match.Length));
DrawAdornment(textViewLines, span);
match = match.NextMatch();
}
艰难的(呃)方式:(来自this article)
/// <summary>
/// This will get the text of the ITextView line as it appears in the actual user editable
/// document.
/// jared parson: https://gist.github.com/4320643
/// </summary>
public static bool TryGetText(IWpfTextView textView, ITextViewLine textViewLine, out string text)
{
var extent = textViewLine.Extent;
var bufferGraph = textView.BufferGraph;
try
{
var collection = bufferGraph.MapDownToSnapshot(extent, SpanTrackingMode.EdgeInclusive, textView.TextSnapshot);
var span = new SnapshotSpan(collection[0].Start, collection[collection.Count - 1].End);
//text = span.ToString();
text = span.GetText();
return true;
}
catch
{
text = null;
return false;
}
}
Regex todoLineRegex = new Regex(@"\/\/\s*TODO\b");
private void CreateVisuals(ITextViewLine line)
{
IWpfTextViewLineCollection textViewLines = _view.TextViewLines;
string text = null;
if (TryGetText(_view, line, out text))
{
var match = todoLineRegex.Match(text);
if (match.Success)
{
int matchStart = line.Start.Position + span.Index;
var span = new SnapshotSpan(_view.TextSnapshot, Span.FromBounds(matchStart, matchStart + match.Length));
DrawAdornment(textViewLines, span);
}
}
}