2013-02-01 211 views
0

我正在編寫一個Visual Studio擴展程序,它爲某種內容類型提供智能感知。 我現在面臨的問題是Visual Studio在用戶輸入字符時在空行上提供的「自動縮進」效果。完成(智能感知)會話時的智能縮進效果

在這裏完成會話開始在一個空行(超過虛擬空間):

before

通知的其他線路的標籤的符號和與在其上插入符的線沒有標籤。

現在,當使用開始打字,VS自動且正確地添加必要的製表符到該行:

after

現在的問題是那些添加了選項卡顯然成爲所述用戶輸入的一部分,並作爲一個結果CurrentSession.SelectedCompletionSet.SelectBestMatch()或者Filter()方法在這裏找不到以「C」開頭的當前項目(思考用戶輸入了\ t \ tC)。

如果我在其他任何不需要自動縮進的地方開始會話,一切正常。

有什麼想法?

編輯(詳細信息):我使用的代碼流非常相似:

在Lua和Clojure中你不會面臨這個問題,因爲他們從不在虛擬空間提供智能(這意味着他們唉ys從一組特定字符開始),並且如果在字符虛擬空間已經變成真實空間之後開始。

另一方面OOK有同樣的問題。

回答

2

修訂的答案:

啊,我明白了。我解釋了你的問題,認爲你指的是通過鍵入完成觸發,而不是來自顯式命令。如果你爲C#編輯器啓用「顯示空白」,你可以看到我們在這裏做了什麼:當你觸發「顯示完成」命令時,我們明確地認識到空白,所以你不再在虛擬空間中浮動。你也應該這樣做。 (或者,您可以通過調整適用範圍來檢測場景並在第一次打字時對其進行修復,但這可能不值得這樣做。)

您可以從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); 
} 

(搞笑一邊:我回答這個問題,我很好奇,想看看我們如何在羅斯林C#和VB編輯負責這個答案是「不」,但過濾後來在代碼中仍然運行純運氣。)

原來的答案:

我你的,你要實現你這樣的完成問題描述懷疑:你知道一個字符將被輸入(通過鍵盤過濾器或IOleCommandTarget)和您觸發一個ICompletionSession,其中跟蹤跨度是當前插入符號位置上的空跨度。

解決這個問題的最佳方法是在鍵被按下並進入編輯器之前而不是觸發會話,而是在它之後。這就是我們在C#和VB完成的Roslyn實現中所做的。然後,當您進行AugmentCompletionSession調用並創建完成集時,計算「適用於」跨度,該跨度由插入符號周圍的非空白字符組成。計算這個最簡單的方法可能是從文本結構導航器調用GetWordExtent

這允許其他場景正常工作。考慮用戶鍵入C,按下轉義鍵,然後繼續輸入標識符的情況。如果你想再次觸發完成,你必須做數學計算,以確保「C」被計算爲跨度的一部分。

+0

謝謝你的回答。調用StartSesion()實際上是在按鍵按下之後**發生的。我首先調用'Next.Exec(pguidCmdGroup,nCmdID,nCmdexecopt,pvaIn,pvaOut)',然後檢查'VSConstants.VSStd2KCmdID.AUTOCOMPLETE',但它再次發生。 VS會在會話開始後和第一次按下按鈕(在Next.Exec(...)之後再次添加這些額外的選項卡) –

+0

另外'AugmentCompletionSession()'在會話開始時只被調用一次。當時的插頁就在虛擬空間上。搜索單詞範圍沒有意義。 –

+0

另:另請參閱我在編輯 –