|
1 "{ Package: 'stx:libwidg' }" |
|
2 |
|
3 EditTextViewCompletionSupport subclass:#WorkspaceCompletionSupport |
|
4 instanceVariableNames:'' |
|
5 classVariableNames:'' |
|
6 poolDictionaries:'' |
|
7 category:'Interface-Smalltalk' |
|
8 ! |
|
9 |
|
10 !WorkspaceCompletionSupport class methodsFor:'documentation'! |
|
11 |
|
12 documentation |
|
13 " |
|
14 A completion support using DWIM to complete code for Smalltalk (and JavaScript) |
|
15 |
|
16 [author:] |
|
17 Claus Gittinger |
|
18 |
|
19 [instance variables:] |
|
20 |
|
21 [class variables:] |
|
22 |
|
23 [see also:] |
|
24 DoWhatIMeanSupport |
|
25 |
|
26 " |
|
27 ! ! |
|
28 |
|
29 !WorkspaceCompletionSupport methodsFor:'private'! |
|
30 |
|
31 computeCompletions |
|
32 |
|
33 |suggestions implementations actions anyFound contextOrNil| |
|
34 |
|
35 "/ a hack |
|
36 (editView topView isKindOf: DebugView) ifTrue:[ |
|
37 contextOrNil := editView topView selectedContext. |
|
38 ]. |
|
39 |
|
40 UserInformation ignoreIn:[ |
|
41 anyFound := false. |
|
42 DoWhatIMeanSupport |
|
43 codeCompletionForLanguage: editView editedLanguage |
|
44 method:editView editedMethod |
|
45 orClass:editView editedClass |
|
46 context:contextOrNil |
|
47 codeView:editView |
|
48 into:[:listOfSuggestions :listOfActions :titleWhenAsking | |
|
49 "/ (listOfSuggestions contains:[:l | l isEmptyOrNil]) ifTrue:[self halt]. |
|
50 suggestions := listOfSuggestions collect:[:entry | entry isArray ifTrue:[entry first] ifFalse:[entry]]. |
|
51 implementations := listOfSuggestions collect:[:entry | entry isArray ifTrue:[entry second] ifFalse:[nil]]. |
|
52 actions := listOfActions. |
|
53 anyFound := true. |
|
54 nil "/ must return nil to avoid DWIM to do it itself (for now) |
|
55 ] |
|
56 ]. |
|
57 "/ anyFound ifFalse:[self halt]. |
|
58 "/ Transcript show:'suggestions: '; showCR:suggestions. |
|
59 "/ Transcript show:'actions: '; showCR:actions. |
|
60 editView sensor |
|
61 pushUserEvent:#'suggestionsArrived:implementations:actions:autoSelect:' |
|
62 for:self |
|
63 withArguments:{suggestions . implementations . actions . autoSelect } |
|
64 |
|
65 "Created: / 26-09-2013 / 17:44:31 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
66 ! |
|
67 |
|
68 suggestionsArrived:suggestionsArg implementations:implementationsArg actions:actionsArg autoSelect:autoSelectArg |
|
69 "the background process has generated some suggestions" |
|
70 |
|
71 |v suggestions implementations actions suggestionOffset keyAndSnippet indexOfSnippet| |
|
72 |
|
73 (editView sensor hasKeyPressEventFor:nil) ifTrue:[ |
|
74 self closeCompletionView. |
|
75 ^ self |
|
76 ]. |
|
77 |
|
78 implementations := implementationsArg. |
|
79 actions := actionsArg. |
|
80 |
|
81 suggestions := suggestionsArg ? #(). |
|
82 suggestions size > 20 ifTrue:[ |
|
83 suggestions := suggestions copyTo:20. |
|
84 implementations := implementations copyTo:20. |
|
85 actions isArray ifTrue:[ actions := actions copyTo:20 ]. |
|
86 ]. |
|
87 |
|
88 "/ append snipplet, if any (can be easily reached via CRSR-up) |
|
89 suggestionOffset := 0. |
|
90 indexOfSnippet := nil. |
|
91 (keyAndSnippet := editView findAbbreviationKeyBeforeCursor) notNil ifTrue:[ |
|
92 |abbrev sniplet i line| |
|
93 |
|
94 abbrev := keyAndSnippet first. |
|
95 sniplet := keyAndSnippet second. |
|
96 |
|
97 "/ if the abbreviation is simply at the end of a longer word, ignore the abbrev. |
|
98 line := editView lineStringBeforeCursor. |
|
99 i := line findLast:[:ch | ch isLetterOrDigit not]. |
|
100 (i < (line size - abbrev size - 1)) ifFalse:[ |
|
101 sniplet := sniplet copyWithout:$!!. |
|
102 |
|
103 "/ true, false and self are often found in both lists |
|
104 (suggestions includes:sniplet) ifFalse:[ |
|
105 suggestions isEmpty ifFalse:[ suggestions := suggestions copyWith: '-' ]. |
|
106 suggestions := suggestions copyWith: ( '%1 %2' |
|
107 bindWith:(sniplet asStringCollection first "contractTo:25") |
|
108 with: ( ('("',abbrev,'" snippet)') colorizeAllWith:Color grey)). |
|
109 indexOfSnippet := suggestions size. |
|
110 |
|
111 "/ change below, when reversing the order in above code |
|
112 "/ suggestionOffset := 2. |
|
113 ] |
|
114 ] |
|
115 ]. |
|
116 suggestions isEmptyOrNil ifTrue:[ |
|
117 self closeCompletionView. |
|
118 ^ self |
|
119 ]. |
|
120 (v := completionView) isNil ifTrue: [ |
|
121 ^ self |
|
122 ]. |
|
123 |
|
124 v sensor |
|
125 pushUserEvent:#value |
|
126 for:[ |
|
127 |top idx preselectIdx performCompletion| |
|
128 |
|
129 (v == completionView) ifTrue: [ |
|
130 top := v topView. |
|
131 |
|
132 LastCompletions notNil ifTrue:[ |
|
133 "/ one of the last completions in list? |
|
134 idx := LastCompletions findFirst:[:compl | suggestions includes:compl]. |
|
135 idx ~~ 0 ifTrue:[ |
|
136 preselectIdx := suggestions indexOf:(LastCompletions at:idx). |
|
137 ]. |
|
138 ]. |
|
139 autoSelectArg ifTrue:[ |
|
140 (preselectIdx isNil and:[suggestions size == 1]) ifTrue:[ |
|
141 preselectIdx := 1. |
|
142 ]. |
|
143 ]. |
|
144 preselectIdx notNil ifTrue:[ |
|
145 |pref| |
|
146 |
|
147 pref := suggestions at:preselectIdx. |
|
148 "/ for now, do not move to front (action needs the index) |
|
149 suggestions at:preselectIdx put:(pref allBold). |
|
150 "/ suggestions removeAtIndex:preselectIdx. |
|
151 "/ suggestions addFirst:(pref allBold). |
|
152 "/ implementations notNil ifTrue:[ |
|
153 "/ implementations removeAtIndex:preselectIdx. |
|
154 "/ implementations addFirst:implementations. |
|
155 "/ ] |
|
156 ]. |
|
157 |
|
158 performCompletion := |
|
159 [:selectedListIndex | |
|
160 |indexInSuggestions| |
|
161 |
|
162 self closeCompletionView. |
|
163 indexInSuggestions := selectedListIndex - suggestionOffset. |
|
164 (selectedListIndex == indexOfSnippet) ifTrue:[ |
|
165 "/ replace the sniplet |
|
166 editView sensor pushUserEvent:#expandAbbreviation for:editView |
|
167 ] ifFalse:[ |
|
168 LastCompletions isNil ifTrue:[ |
|
169 LastCompletions := OrderedCollection new. |
|
170 ]. |
|
171 LastCompletions add:(suggestions at:indexInSuggestions). |
|
172 LastCompletions size > 200 ifTrue:[ |
|
173 LastCompletions removeLast |
|
174 ]. |
|
175 |
|
176 actions notNil ifTrue:[ |
|
177 actions isBlock ifTrue:[ |
|
178 actions value:indexInSuggestions |
|
179 ] ifFalse:[ |
|
180 (actions at:indexInSuggestions) value |
|
181 ]. |
|
182 ]. |
|
183 ]. |
|
184 "/ disabled - user has made his choice; so don't show more suggestions |
|
185 "/ editView sensor pushUserEvent:#updateCompletionList for:self |
|
186 ]. |
|
187 |
|
188 ((suggestions size == 1) and:[preselectIdx == 1]) ifTrue:[ |
|
189 "/ do it, right here and now |
|
190 performCompletion value:preselectIdx. |
|
191 ] ifFalse:[ |
|
192 top open. |
|
193 v list:suggestions |
|
194 expandTabs:false scanForNonStrings:false |
|
195 includesNonStrings:false redraw:true. |
|
196 |
|
197 implementations notNil ifTrue:[ |
|
198 implementations keysAndValuesDo:[:idx :impls | |
|
199 |implsMenu| |
|
200 |
|
201 impls notEmptyOrNil ifTrue:[ |
|
202 implsMenu := Menu new. |
|
203 impls do:[:each | |
|
204 implsMenu addItem:(MenuItem new label:each name). |
|
205 ]. |
|
206 v subMenuAt:idx put:implsMenu |
|
207 ]. |
|
208 ]. |
|
209 ]. |
|
210 |
|
211 v enable:true. |
|
212 preselectIdx notNil ifTrue:[ |
|
213 "/ very disturbing!! |
|
214 v selection:preselectIdx. |
|
215 ]. |
|
216 v extent:completionView preferredExtentForContents. |
|
217 v action:performCompletion. |
|
218 |
|
219 (top ~~ v) ifTrue:[ |
|
220 top resizeToFit. |
|
221 top bottom > v device usableHeight ifTrue:[ |
|
222 top origin:((top origin x) @ (v device usableHeight - v height)). |
|
223 ]. |
|
224 top raise. |
|
225 ] |
|
226 ] |
|
227 ] |
|
228 ] |
|
229 ! ! |
|
230 |
|
231 !WorkspaceCompletionSupport class methodsFor:'documentation'! |
|
232 |
|
233 version |
|
234 ^ '$Header: /cvs/stx/stx/libwidg/WorkspaceCompletionSupport.st,v 1.1 2013-09-26 17:07:44 vrany Exp $' |
|
235 ! |
|
236 |
|
237 version_CVS |
|
238 ^ '$Header: /cvs/stx/stx/libwidg/WorkspaceCompletionSupport.st,v 1.1 2013-09-26 17:07:44 vrany Exp $' |
|
239 ! ! |
|
240 |