--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WorkspaceCompletionSupport.st Thu Sep 26 19:07:44 2013 +0200
@@ -0,0 +1,240 @@
+"{ Package: 'stx:libwidg' }"
+
+EditTextViewCompletionSupport subclass:#WorkspaceCompletionSupport
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Smalltalk'
+!
+
+!WorkspaceCompletionSupport class methodsFor:'documentation'!
+
+documentation
+"
+ A completion support using DWIM to complete code for Smalltalk (and JavaScript)
+
+ [author:]
+ Claus Gittinger
+
+ [instance variables:]
+
+ [class variables:]
+
+ [see also:]
+ DoWhatIMeanSupport
+
+"
+! !
+
+!WorkspaceCompletionSupport methodsFor:'private'!
+
+computeCompletions
+
+ |suggestions implementations actions anyFound contextOrNil|
+
+ "/ a hack
+ (editView topView isKindOf: DebugView) ifTrue:[
+ contextOrNil := editView topView selectedContext.
+ ].
+
+ UserInformation ignoreIn:[
+ anyFound := false.
+ DoWhatIMeanSupport
+ codeCompletionForLanguage: editView editedLanguage
+ method:editView editedMethod
+ orClass:editView editedClass
+ context:contextOrNil
+ codeView:editView
+ into:[:listOfSuggestions :listOfActions :titleWhenAsking |
+"/ (listOfSuggestions contains:[:l | l isEmptyOrNil]) ifTrue:[self halt].
+ suggestions := listOfSuggestions collect:[:entry | entry isArray ifTrue:[entry first] ifFalse:[entry]].
+ implementations := listOfSuggestions collect:[:entry | entry isArray ifTrue:[entry second] ifFalse:[nil]].
+ actions := listOfActions.
+ anyFound := true.
+ nil "/ must return nil to avoid DWIM to do it itself (for now)
+ ]
+ ].
+ "/ anyFound ifFalse:[self halt].
+ "/ Transcript show:'suggestions: '; showCR:suggestions.
+ "/ Transcript show:'actions: '; showCR:actions.
+ editView sensor
+ pushUserEvent:#'suggestionsArrived:implementations:actions:autoSelect:'
+ for:self
+ withArguments:{suggestions . implementations . actions . autoSelect }
+
+ "Created: / 26-09-2013 / 17:44:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+suggestionsArrived:suggestionsArg implementations:implementationsArg actions:actionsArg autoSelect:autoSelectArg
+ "the background process has generated some suggestions"
+
+ |v suggestions implementations actions suggestionOffset keyAndSnippet indexOfSnippet|
+
+ (editView sensor hasKeyPressEventFor:nil) ifTrue:[
+ self closeCompletionView.
+ ^ self
+ ].
+
+ implementations := implementationsArg.
+ actions := actionsArg.
+
+ suggestions := suggestionsArg ? #().
+ suggestions size > 20 ifTrue:[
+ suggestions := suggestions copyTo:20.
+ implementations := implementations copyTo:20.
+ actions isArray ifTrue:[ actions := actions copyTo:20 ].
+ ].
+
+ "/ append snipplet, if any (can be easily reached via CRSR-up)
+ suggestionOffset := 0.
+ indexOfSnippet := nil.
+ (keyAndSnippet := editView findAbbreviationKeyBeforeCursor) notNil ifTrue:[
+ |abbrev sniplet i line|
+
+ abbrev := keyAndSnippet first.
+ sniplet := keyAndSnippet second.
+
+ "/ if the abbreviation is simply at the end of a longer word, ignore the abbrev.
+ line := editView lineStringBeforeCursor.
+ i := line findLast:[:ch | ch isLetterOrDigit not].
+ (i < (line size - abbrev size - 1)) ifFalse:[
+ sniplet := sniplet copyWithout:$!!.
+
+ "/ true, false and self are often found in both lists
+ (suggestions includes:sniplet) ifFalse:[
+ suggestions isEmpty ifFalse:[ suggestions := suggestions copyWith: '-' ].
+ suggestions := suggestions copyWith: ( '%1 %2'
+ bindWith:(sniplet asStringCollection first "contractTo:25")
+ with: ( ('("',abbrev,'" snippet)') colorizeAllWith:Color grey)).
+ indexOfSnippet := suggestions size.
+
+ "/ change below, when reversing the order in above code
+ "/ suggestionOffset := 2.
+ ]
+ ]
+ ].
+ suggestions isEmptyOrNil ifTrue:[
+ self closeCompletionView.
+ ^ self
+ ].
+ (v := completionView) isNil ifTrue: [
+ ^ self
+ ].
+
+ v sensor
+ pushUserEvent:#value
+ for:[
+ |top idx preselectIdx performCompletion|
+
+ (v == completionView) ifTrue: [
+ top := v topView.
+
+ LastCompletions notNil ifTrue:[
+ "/ one of the last completions in list?
+ idx := LastCompletions findFirst:[:compl | suggestions includes:compl].
+ idx ~~ 0 ifTrue:[
+ preselectIdx := suggestions indexOf:(LastCompletions at:idx).
+ ].
+ ].
+ autoSelectArg ifTrue:[
+ (preselectIdx isNil and:[suggestions size == 1]) ifTrue:[
+ preselectIdx := 1.
+ ].
+ ].
+ preselectIdx notNil ifTrue:[
+ |pref|
+
+ pref := suggestions at:preselectIdx.
+ "/ for now, do not move to front (action needs the index)
+ suggestions at:preselectIdx put:(pref allBold).
+"/ suggestions removeAtIndex:preselectIdx.
+"/ suggestions addFirst:(pref allBold).
+"/ implementations notNil ifTrue:[
+"/ implementations removeAtIndex:preselectIdx.
+"/ implementations addFirst:implementations.
+"/ ]
+ ].
+
+ performCompletion :=
+ [:selectedListIndex |
+ |indexInSuggestions|
+
+ self closeCompletionView.
+ indexInSuggestions := selectedListIndex - suggestionOffset.
+ (selectedListIndex == indexOfSnippet) ifTrue:[
+ "/ replace the sniplet
+ editView sensor pushUserEvent:#expandAbbreviation for:editView
+ ] ifFalse:[
+ LastCompletions isNil ifTrue:[
+ LastCompletions := OrderedCollection new.
+ ].
+ LastCompletions add:(suggestions at:indexInSuggestions).
+ LastCompletions size > 200 ifTrue:[
+ LastCompletions removeLast
+ ].
+
+ actions notNil ifTrue:[
+ actions isBlock ifTrue:[
+ actions value:indexInSuggestions
+ ] ifFalse:[
+ (actions at:indexInSuggestions) value
+ ].
+ ].
+ ].
+ "/ disabled - user has made his choice; so don't show more suggestions
+ "/ editView sensor pushUserEvent:#updateCompletionList for:self
+ ].
+
+ ((suggestions size == 1) and:[preselectIdx == 1]) ifTrue:[
+ "/ do it, right here and now
+ performCompletion value:preselectIdx.
+ ] ifFalse:[
+ top open.
+ v list:suggestions
+ expandTabs:false scanForNonStrings:false
+ includesNonStrings:false redraw:true.
+
+ implementations notNil ifTrue:[
+ implementations keysAndValuesDo:[:idx :impls |
+ |implsMenu|
+
+ impls notEmptyOrNil ifTrue:[
+ implsMenu := Menu new.
+ impls do:[:each |
+ implsMenu addItem:(MenuItem new label:each name).
+ ].
+ v subMenuAt:idx put:implsMenu
+ ].
+ ].
+ ].
+
+ v enable:true.
+ preselectIdx notNil ifTrue:[
+ "/ very disturbing!!
+ v selection:preselectIdx.
+ ].
+ v extent:completionView preferredExtentForContents.
+ v action:performCompletion.
+
+ (top ~~ v) ifTrue:[
+ top resizeToFit.
+ top bottom > v device usableHeight ifTrue:[
+ top origin:((top origin x) @ (v device usableHeight - v height)).
+ ].
+ top raise.
+ ]
+ ]
+ ]
+ ]
+! !
+
+!WorkspaceCompletionSupport class methodsFor:'documentation'!
+
+version
+ ^ '$Header: /cvs/stx/stx/libwidg/WorkspaceCompletionSupport.st,v 1.1 2013-09-26 17:07:44 vrany Exp $'
+!
+
+version_CVS
+ ^ '$Header: /cvs/stx/stx/libwidg/WorkspaceCompletionSupport.st,v 1.1 2013-09-26 17:07:44 vrany Exp $'
+! !
+