我正在编写一个Visual Studio扩展,为某种内容类型提供智能感知。 我现在面临的问题是当用户键入字符时,Visual Studio在空行上提供的“自动缩进”效果。
这里的一个完成会话是在空行(虚拟空间)上开始的:
注意其他行上的标签符号,并且没有带插入符号的行上的标签。
现在,当使用开始输入时,VS会自动并正确地将必要的制表符添加到该行:
现在的问题是那些已添加的标签明显成为用户输入的一部分,因此CurrentSession.SelectedCompletionSet.SelectBestMatch()
或Filter()
方法找不到当前以“C”开头的项目(思考用户输入的内容) \ t \ t \ t \ tC而不是)。
如果我在其他任何不需要自动缩进的地方开始会话,一切正常。
有什么想法吗?
编辑(更多信息):我使用的代码流非常类似于:
在Lua和Clojure中你不会遇到这个问题,因为它们从不在虚拟空间上提供智能感知(意味着它们总是在一组特定字符之后开始),并且如果你在角色虚拟空间已经变成真实空间之后开始。
Ook在另一方遇到了同样的问题。
答案 0 :(得分:2)
修订答案:
啊,我明白了。我解释你的问题,认为你指的是通过输入完成触发,而不是来自显式命令。如果为C#编辑器启用“show whitespace”,你可以看到我们在这里做的事情:当你触发“show completion”命令时,我们明确地意识到空白,所以你不再在虚拟空间中漂浮。你也应该这样做。 (或者,您可以通过调整ApplicableTo跨度来检测方案并在第一次输入时进行修复,但这可能不值得。)您可以从IEditorOperations中获取应插入的空格。所以MEF导入IEditorOperationsFactoryService,然后执行:
var editorOperations = editorOperationsFactoryService.GetEditorOperations(textView);
var whitespace = editorOperations.GetWhitespaceForVirtualSpace(textView.Caret.Position.VirtualBufferPosition);
if (whitespace.Length != 0)
{
textView.TextBuffer.Insert(textView.Caret.Position.BufferPosition, whitespace);
}
(有趣的是:当我回答这个问题时,我很想知道我们是如何在Roslyn C#和VB编辑器中处理这个问题的。答案是“不是”,但过滤仍然可以通过代码后面的纯粹运气来实现。)< / p>
原始答案:
我怀疑您对问题的描述是否正在实现这样的完成:您知道将要键入一个字符(通过键盘过滤器或IOleCommandTarget
)并触发ICompletionSession,其中跟踪跨度是当前插入位置的空跨度。
解决此问题的最佳方法是在按下键并进入编辑器之前不触发会话,而是在其之后触发。这就是我们在C#和VB完成的Roslyn实现中所做的。然后,当您进入AugmentCompletionSession调用并创建CompletionSet时,请计算“适用于”范围,该范围由您的插入符号周围的非空白字符组成。计算这个的最简单方法可能就是从文本结构导航器中调用GetWordExtent
。
这允许其他方案正常工作。考虑用户键入C,按下escape,然后继续键入标识符的场景。如果你想再次触发完成,你必须进行数学运算,以确保“C”被计算为你的范围的一部分。