Workspace.st
changeset 4799 4baf5f98c387
parent 4784 c8866890363a
child 4815 f75345885ad7
--- a/Workspace.st	Thu Sep 26 19:34:39 2013 +0200
+++ b/Workspace.st	Thu Sep 26 19:34:48 2013 +0200
@@ -25,13 +25,6 @@
 	category:'Interface-Smalltalk'
 !
 
-Object subclass:#CodeCompletionService
-	instanceVariableNames:'completionView completionProcess editView autoSelect'
-	classVariableNames:'LastCompletions'
-	poolDictionaries:''
-	privateIn:Workspace
-!
-
 Workspace comment:''
 !
 
@@ -125,8 +118,10 @@
 
 !Workspace class methodsFor:'defaults'!
 
-codeCompletionServiceClass
-    ^ CodeCompletionService
+defaultCompletionSupportClass
+    ^ WorkspaceCompletionSupport
+
+    "Created: / 26-09-2013 / 17:59:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 defaultLabel
@@ -2191,419 +2186,13 @@
     "Modified (comment): / 07-03-2012 / 17:52:59 / cg"
 ! !
 
-!Workspace::CodeCompletionService class methodsFor:'instance creation'!
-
-for:anEditView
-    ^ self new editView:anEditView
-! !
-
-!Workspace::CodeCompletionService methodsFor:'accessing'!
-
-editView:something
-    editView := something.
-! !
-
-!Workspace::CodeCompletionService methodsFor:'events'!
-
-buttonPress:button x:x y:y
-    self closeCompletionView.
-!
-
-editViewLostFocus
-    completionView notNil ifTrue:[
-        self closeCompletionView
-    ]
-!
-
-handleKeyPress:key x:x y:y
-    "return true, if I have eaten this keypress"
-
-    |ch completeImmediate eatCursorLeftOrRight|
-
-    completeImmediate := UserPreferences current immediateCodeCompletion.
-    
-    "/ open on CTRL- or TAB-key?
-    (completionView isNil or:[completionView realized not]) ifTrue:[
-        editView hasSelection ifFalse:[
-            ((ch := editView characterBeforeCursor) notNil "/ i.e. not at begin of line
-            and:[ ch isSeparator not ]) ifTrue:[
-                (key == #Control_L or:[ key == #Ctrl or:[ key == #Control_R or:[ key == #Control]]]) ifTrue:[
-                    UserPreferences current codeCompletionOnControlKey ifTrue:[
-                        autoSelect := true.
-                        self updateCompletionList
-                    ]
-                ].
-                (key == #Tab) ifTrue:[
-                    UserPreferences current codeCompletionOnTabKey ifTrue:[
-                        autoSelect := true.
-                        self updateCompletionList.
-                        ^ true
-                    ].
-                ]
-            ].
-        ].
-        ^ false.
-    ].
-
-    "/ key for completion view ? (careful: do not forward too many, it would disturb user's typing)
-    key isCharacter ifFalse:[
-        "/ forward to menu
-        (completionView notNil) ifTrue:[
-            eatCursorLeftOrRight := false.
-"/                                    completeImmediate not
-"/                                    or:[ editView sensor shiftDown 
-"/                                    or:[ editView sensor ctrlDown ]].
-            (key == #CursorDown 
-                or:[ (key == #CursorUp)
-                or:[ ((key == #CursorLeft) and:[eatCursorLeftOrRight])
-                or:[ ((key == #CursorRight) and:[eatCursorLeftOrRight])
-                or:[ ((key == #Return) and:[ completionView hasSelection ])
-            ]]]]) ifTrue:[
-                "/ only with shift - normal user typing should not interfere with completion
-                true "editView sensor shiftDown" ifTrue:[
-                    "/ forward to completion view
-                    completionView sensor pushUserEvent:#value for:[ completionView keyPress:key x:0 y:0 ].
-                    ^ true.
-                ].
-            ].
-
-            (key == #Control_L or:[ key == #Control_R or:[ key == #Control or:[ key == #Ctrl ]]]) ifTrue:[
-                "/ CTRL is a toggle
-                self closeCompletionView.   
-                ^ true.
-                "/ ^ false
-            ].
-            (key == #Escape) ifTrue:[
-                self closeCompletionView.
-                ^ true  "/ EAT
-            ].
-            "/ shift does not close
-            (key == #Shift_L or:[ key == #Shift_R or:[ key == #Shift]]) ifTrue:[
-                ^ false "/ don' eat
-            ].
-
-            self closeCompletionView.
-            ^ false "/ don' eat
-        ].
-    ].
-    ^ false.
-!
-
-postKeyPress:key
-    UserPreferences current immediateCodeCompletion ifFalse:[
-        "/ only update, if already open
-        completionView isNil ifTrue:[^ self].
-    ].
-
-    (key == #BackSpace or:[key == #BasicBackspace]) ifTrue:[
-        autoSelect := false.
-        self updateCompletionList.
-        ^ self
-    ].
-
-    key isCharacter ifTrue:[
-        key isSeparator ifTrue:[
-            self closeCompletionView
-        ] ifFalse:[
-            autoSelect := false.
-            self updateCompletionList.
-        ].
-        ^ self
-    ].
-! !
-
-!Workspace::CodeCompletionService methodsFor:'private'!
-
-closeCompletionView
-    |v|
-
-    (v := completionView) notNil ifTrue:[
-        completionView := nil.
-        "/ let it close itself - avoids synchronization problems
-        v sensor
-            pushUserEvent:#value
-            for:[ v topView destroy ]
-    ].
-!
-
-release
-    self stopCompletionProcess.
-    self closeCompletionView.
-    super release
-!
-
-startCompletionProcess
-    "start the code completion process in the background"
-
-    |movePos topView initialList cursorX cursorY|
-
-    "/ terminate any previous process
-    self stopCompletionProcess.
-
-    (editView sensor hasKeyPressEventFor:nil) ifTrue:[ 
-        self closeCompletionView. 
-        ^ self
-    ].
-    ((cursorX := editView xOfCursor) isNil
-    or:[ (cursorY := editView yOfCursor) isNil ]) ifTrue:[
-        "/ no cursor - user is selecting, or cursor has been scrolled out of sight.
-        self closeCompletionView. 
-        ^ self
-    ].
-
-    initialList := #( 'busy...' ).
-
-    "/ move the window
-    movePos := editView device translatePoint:(cursorX @ cursorY) fromView:editView toView:nil.
-    movePos := movePos - (editView viewOrigin x @ 0).
-    "/ currently, we have to stay away a bit, to avoid getting the focus
-    movePos := movePos + (60 @ (editView font height)).
-
-    completionView isNil ifTrue:[
-        completionView := CodeCompletionHelpMenuView new.
-        completionView name:'completion'.
-        completionView level:0.
-        completionView list:initialList.
-        completionView enable:false.
-        completionView extent:completionView preferredExtentForContents.
-        topView := CodeCompletionHelpView with:completionView.
-        topView origin:movePos.
-        topView resizeToFit.
-        "/ topView open.
-    ] ifFalse:[
-        completionView list:initialList.
-        topView := completionView topView.
-        topView ~~ completionView ifTrue:[
-            topView origin:movePos.
-            topView resizeToFit.
-        ]
-    ].
-
-    completionProcess := 
-        [
-            |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 }
-        ] forkAt:(Processor activePriority - 1).
-
-    "Modified: / 18-09-2013 / 14:17:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-stopCompletionProcess
-    "kill any background completion process"
-
-    |p|
-
-    (p := completionProcess) notNil ifTrue:[
-        completionProcess := nil.
-        p terminate.
-    ].
-!
-
-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.
-                    ]
-                ]
-            ]
-        ]
-!
-
-updateCompletionList
-    "called for keypress events"
-
-    self startCompletionProcess.
-! !
-
 !Workspace class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg/Workspace.st,v 1.308 2013-09-24 15:21:54 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg/Workspace.st,v 1.309 2013-09-26 17:34:48 vrany Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libwidg/Workspace.st,v 1.308 2013-09-24 15:21:54 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg/Workspace.st,v 1.309 2013-09-26 17:34:48 vrany Exp $'
 ! !