1+ using System ;
2+ using System . Runtime . InteropServices ;
3+ using Microsoft . VisualStudio ;
4+ using Microsoft . VisualStudio . Language . Intellisense ;
5+ using Microsoft . VisualStudio . OLE . Interop ;
6+ using Microsoft . VisualStudio . Text ;
7+ using Microsoft . VisualStudio . Text . Editor ;
8+
9+ namespace EditorConfig . VisualStudio
10+ {
11+ internal sealed class CommandFilter : IOleCommandTarget
12+ {
13+ private ICompletionSession _currentSession ;
14+
15+ public CommandFilter ( IWpfTextView textView , ICompletionBroker broker )
16+ {
17+ _currentSession = null ;
18+
19+ TextView = textView ;
20+ Broker = broker ;
21+ }
22+
23+ public IWpfTextView TextView { get ; private set ; }
24+ public ICompletionBroker Broker { get ; private set ; }
25+ public IOleCommandTarget Next { get ; set ; }
26+
27+ private static char GetTypeChar ( IntPtr pvaIn )
28+ {
29+ return ( char ) ( ushort ) Marshal . GetObjectForNativeVariant ( pvaIn ) ;
30+ }
31+
32+ public int Exec ( ref Guid pguidCmdGroup , uint nCmdID , uint nCmdexecopt , IntPtr pvaIn , IntPtr pvaOut )
33+ {
34+ bool handled = false ;
35+ int hresult = VSConstants . S_OK ;
36+
37+ // 1. Pre-process
38+ if ( pguidCmdGroup == VSConstants . VSStd2K )
39+ {
40+ switch ( ( VSConstants . VSStd2KCmdID ) nCmdID )
41+ {
42+ case VSConstants . VSStd2KCmdID . AUTOCOMPLETE :
43+ case VSConstants . VSStd2KCmdID . COMPLETEWORD :
44+ case VSConstants . VSStd2KCmdID . SHOWMEMBERLIST :
45+ handled = StartSession ( ) ;
46+ break ;
47+ case VSConstants . VSStd2KCmdID . RETURN :
48+ handled = Complete ( false ) ;
49+ break ;
50+ case VSConstants . VSStd2KCmdID . TAB :
51+ handled = Complete ( true ) ;
52+ break ;
53+ case VSConstants . VSStd2KCmdID . CANCEL :
54+ handled = Cancel ( ) ;
55+ break ;
56+ }
57+ }
58+
59+ if ( ! handled )
60+ hresult = Next . Exec ( pguidCmdGroup , nCmdID , nCmdexecopt , pvaIn , pvaOut ) ;
61+
62+ if ( ErrorHandler . Succeeded ( hresult ) )
63+ {
64+ if ( pguidCmdGroup == VSConstants . VSStd2K )
65+ {
66+ switch ( ( VSConstants . VSStd2KCmdID ) nCmdID )
67+ {
68+ case VSConstants . VSStd2KCmdID . TYPECHAR :
69+ char ch = GetTypeChar ( pvaIn ) ;
70+ if ( ch == '=' || ch == ' ' )
71+ Cancel ( ) ;
72+ else if ( ! char . IsPunctuation ( ch ) && ! char . IsControl ( ch ) )
73+ StartSession ( ) ;
74+ else if ( _currentSession != null )
75+ Filter ( ) ;
76+ break ;
77+ case VSConstants . VSStd2KCmdID . BACKSPACE :
78+ if ( _currentSession == null )
79+ StartSession ( ) ;
80+
81+ Filter ( ) ;
82+ break ;
83+ }
84+ }
85+ }
86+
87+ return hresult ;
88+ }
89+
90+ private void Filter ( )
91+ {
92+ if ( _currentSession == null )
93+ return ;
94+
95+ _currentSession . SelectedCompletionSet . SelectBestMatch ( ) ;
96+ _currentSession . SelectedCompletionSet . Recalculate ( ) ;
97+ }
98+
99+ bool Cancel ( )
100+ {
101+ if ( _currentSession == null )
102+ return false ;
103+
104+ _currentSession . Dismiss ( ) ;
105+
106+ return true ;
107+ }
108+
109+ bool Complete ( bool force )
110+ {
111+ if ( _currentSession == null )
112+ return false ;
113+
114+ if ( ! _currentSession . SelectedCompletionSet . SelectionStatus . IsSelected && ! force )
115+ {
116+ _currentSession . Dismiss ( ) ;
117+ return false ;
118+ }
119+ else
120+ {
121+ _currentSession . Commit ( ) ;
122+ return true ;
123+ }
124+ }
125+
126+ bool StartSession ( )
127+ {
128+ if ( _currentSession != null )
129+ return false ;
130+
131+ SnapshotPoint caret = TextView . Caret . Position . BufferPosition ;
132+ ITextSnapshot snapshot = caret . Snapshot ;
133+
134+ if ( ! Broker . IsCompletionActive ( TextView ) )
135+ {
136+ _currentSession = Broker . CreateCompletionSession ( TextView , snapshot . CreateTrackingPoint ( caret , PointTrackingMode . Positive ) , true ) ;
137+ }
138+ else
139+ {
140+ _currentSession = Broker . GetSessions ( TextView ) [ 0 ] ;
141+ }
142+ _currentSession . Dismissed += ( sender , args ) => _currentSession = null ;
143+
144+ if ( ! _currentSession . IsStarted )
145+ _currentSession . Start ( ) ;
146+
147+ return true ;
148+ }
149+
150+ public int QueryStatus ( ref Guid pguidCmdGroup , uint cCmds , OLECMD [ ] prgCmds , IntPtr pCmdText )
151+ {
152+ if ( pguidCmdGroup == VSConstants . VSStd2K )
153+ {
154+ switch ( ( VSConstants . VSStd2KCmdID ) prgCmds [ 0 ] . cmdID )
155+ {
156+ case VSConstants . VSStd2KCmdID . AUTOCOMPLETE :
157+ case VSConstants . VSStd2KCmdID . COMPLETEWORD :
158+ case VSConstants . VSStd2KCmdID . SHOWMEMBERLIST :
159+ prgCmds [ 0 ] . cmdf = ( uint ) OLECMDF . OLECMDF_ENABLED | ( uint ) OLECMDF . OLECMDF_SUPPORTED ;
160+ return VSConstants . S_OK ;
161+ }
162+ }
163+ return Next . QueryStatus ( pguidCmdGroup , cCmds , prgCmds , pCmdText ) ;
164+ }
165+ }
166+ }
0 commit comments