Initial support for per-language edit support.
authorJan Vrany <jan.vrany@fit.cvut.cz>
Thu, 25 Jul 2013 11:34:26 +0100
changeset 39 748389119d0a
parent 38 c7137bdf49e2
child 40 85eaf579889b
Initial support for per-language edit support. Some work on Smalltalk edit support, namely on electric blocks. Works fine, but need more work to make it usable but not too intrusive.
Make.proto
Make.spec
SmallSenseEditSupport.st
SmallSenseGenericEditSupport.st
SmallSenseParserTests.st
SmallSenseRecognizer.st
SmallSenseRecognizerTests.st
SmallSenseService.st
SmallSenseSmalltalkEditSupport.st
abbrev.stc
bc.mak
jv_smallsense.st
libInit.cc
smallsense.rc
--- a/Make.proto	Wed Jul 24 17:06:19 2013 +0100
+++ b/Make.proto	Thu Jul 25 11:34:26 2013 +0100
@@ -162,6 +162,7 @@
 $(OUTDIR)SmallSenseChecker.$(O) SmallSenseChecker.$(H): SmallSenseChecker.st $(INCLUDE_TOP)/stx/goodies/refactoryBrowser/lint/SmalllintChecker.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseCompletionWindow.$(O) SmallSenseCompletionWindow.$(H): SmallSenseCompletionWindow.st $(INCLUDE_TOP)/stx/libview2/SimpleDialog.$(H) $(INCLUDE_TOP)/stx/libview2/ApplicationModel.$(H) $(INCLUDE_TOP)/stx/libview2/Model.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseCriticsWindow.$(O) SmallSenseCriticsWindow.$(H): SmallSenseCriticsWindow.st $(INCLUDE_TOP)/stx/libview2/ApplicationModel.$(H) $(INCLUDE_TOP)/stx/libview2/Model.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)SmallSenseEditSupport.$(O) SmallSenseEditSupport.$(H): SmallSenseEditSupport.st $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseInfo.$(O) SmallSenseInfo.$(H): SmallSenseInfo.st $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseManager.$(O) SmallSenseManager.$(H): SmallSenseManager.st $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSensePO.$(O) SmallSensePO.$(H): SmallSensePO.st $(INCLUDE_TOP)/stx/libwidg2/HierarchicalItem.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
@@ -187,9 +188,11 @@
 $(OUTDIR)SmallSenseClassType.$(O) SmallSenseClassType.$(H): SmallSenseClassType.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseType.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseConstantPO.$(O) SmallSenseConstantPO.$(H): SmallSenseConstantPO.st $(INCLUDE_TOP)/jv/smallsense/SmallSensePO.$(H) $(INCLUDE_TOP)/stx/libwidg2/HierarchicalItem.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseFinder.$(O) SmallSenseFinder.$(H): SmallSenseFinder.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseParseNodeVisitor.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)SmallSenseGenericEditSupport.$(O) SmallSenseGenericEditSupport.$(H): SmallSenseGenericEditSupport.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseEditSupport.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseInferencer.$(O) SmallSenseInferencer.$(H): SmallSenseInferencer.st $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(INCLUDE_TOP)/jv/smallsense/SmallSenseParseNodeVisitor.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseMethodInfo.$(O) SmallSenseMethodInfo.$(H): SmallSenseMethodInfo.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseInfo.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseMethodPO.$(O) SmallSenseMethodPO.$(H): SmallSenseMethodPO.st $(INCLUDE_TOP)/jv/smallsense/SmallSensePO.$(H) $(INCLUDE_TOP)/stx/libwidg2/HierarchicalItem.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)SmallSenseSmalltalkEditSupport.$(O) SmallSenseSmalltalkEditSupport.$(H): SmallSenseSmalltalkEditSupport.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseEditSupport.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseSnippetPO.$(O) SmallSenseSnippetPO.$(H): SmallSenseSnippetPO.st $(INCLUDE_TOP)/jv/smallsense/SmallSensePO.$(H) $(INCLUDE_TOP)/stx/libwidg2/HierarchicalItem.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseUnionType.$(O) SmallSenseUnionType.$(H): SmallSenseUnionType.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseType.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseUnknownType.$(O) SmallSenseUnknownType.$(H): SmallSenseUnknownType.st $(INCLUDE_TOP)/jv/smallsense/SmallSenseType.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
--- a/Make.spec	Wed Jul 24 17:06:19 2013 +0100
+++ b/Make.spec	Thu Jul 25 11:34:26 2013 +0100
@@ -53,6 +53,7 @@
 	SmallSenseChecker \
 	SmallSenseCompletionWindow \
 	SmallSenseCriticsWindow \
+	SmallSenseEditSupport \
 	SmallSenseInfo \
 	SmallSenseManager \
 	SmallSensePO \
@@ -78,9 +79,11 @@
 	SmallSenseClassType \
 	SmallSenseConstantPO \
 	SmallSenseFinder \
+	SmallSenseGenericEditSupport \
 	SmallSenseInferencer \
 	SmallSenseMethodInfo \
 	SmallSenseMethodPO \
+	SmallSenseSmalltalkEditSupport \
 	SmallSenseSnippetPO \
 	SmallSenseUnionType \
 	SmallSenseUnknownType \
@@ -94,6 +97,7 @@
     $(OUTDIR_SLASH)SmallSenseChecker.$(O) \
     $(OUTDIR_SLASH)SmallSenseCompletionWindow.$(O) \
     $(OUTDIR_SLASH)SmallSenseCriticsWindow.$(O) \
+    $(OUTDIR_SLASH)SmallSenseEditSupport.$(O) \
     $(OUTDIR_SLASH)SmallSenseInfo.$(O) \
     $(OUTDIR_SLASH)SmallSenseManager.$(O) \
     $(OUTDIR_SLASH)SmallSensePO.$(O) \
@@ -119,9 +123,11 @@
     $(OUTDIR_SLASH)SmallSenseClassType.$(O) \
     $(OUTDIR_SLASH)SmallSenseConstantPO.$(O) \
     $(OUTDIR_SLASH)SmallSenseFinder.$(O) \
+    $(OUTDIR_SLASH)SmallSenseGenericEditSupport.$(O) \
     $(OUTDIR_SLASH)SmallSenseInferencer.$(O) \
     $(OUTDIR_SLASH)SmallSenseMethodInfo.$(O) \
     $(OUTDIR_SLASH)SmallSenseMethodPO.$(O) \
+    $(OUTDIR_SLASH)SmallSenseSmalltalkEditSupport.$(O) \
     $(OUTDIR_SLASH)SmallSenseSnippetPO.$(O) \
     $(OUTDIR_SLASH)SmallSenseUnionType.$(O) \
     $(OUTDIR_SLASH)SmallSenseUnknownType.$(O) \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmallSenseEditSupport.st	Thu Jul 25 11:34:26 2013 +0100
@@ -0,0 +1,55 @@
+"{ Package: 'jv:smallsense' }"
+
+Object subclass:#SmallSenseEditSupport
+	instanceVariableNames:'service textView'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'SmallSense-Interface'
+!
+
+!SmallSenseEditSupport class methodsFor:'instance creation'!
+
+forLanguage: aProgrammingLanguage
+    aProgrammingLanguage notNil ifTrue:[
+        aProgrammingLanguage isSmalltalk ifTrue:[
+            ^SmallSenseSmalltalkEditSupport new
+        ].
+    ].
+
+    ^SmallSenseGenericEditSupport new.
+
+    "Created: / 24-07-2013 / 23:20:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SmallSenseEditSupport methodsFor:'accessing'!
+
+language
+    ^ self subclassResponsibility.
+
+    "Created: / 24-07-2013 / 23:44:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+service
+    ^ service
+!
+
+service:aSmallSenseService
+    service := aSmallSenseService.
+    textView := aSmallSenseService textView.
+
+    "Modified: / 25-07-2013 / 00:11:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SmallSenseEditSupport methodsFor:'event handling'!
+
+keyPress: key x:x y:y in: view
+
+    "Handles an event in given view (a subview of codeView).
+     If the method returns true, the event will not be processed
+     by the view."
+
+    ^false
+
+    "Created: / 24-07-2013 / 23:31:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmallSenseGenericEditSupport.st	Thu Jul 25 11:34:26 2013 +0100
@@ -0,0 +1,17 @@
+"{ Package: 'jv:smallsense' }"
+
+SmallSenseEditSupport subclass:#SmallSenseGenericEditSupport
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	category:'SmallSense-Interface'
+!
+
+!SmallSenseGenericEditSupport methodsFor:'accessing'!
+
+language
+    ^nil
+
+    "Created: / 24-07-2013 / 23:44:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
--- a/SmallSenseParserTests.st	Wed Jul 24 17:06:19 2013 +0100
+++ b/SmallSenseParserTests.st	Thu Jul 25 11:34:26 2013 +0100
@@ -873,3 +873,4 @@
 version_SVN
     ^ '$Id: SmallSenseParserTests.st 7694 2011-04-04 19:53:25Z vranyj1 $'
 ! !
+
--- a/SmallSenseRecognizer.st	Wed Jul 24 17:06:19 2013 +0100
+++ b/SmallSenseRecognizer.st	Thu Jul 25 11:34:26 2013 +0100
@@ -165,13 +165,14 @@
     | class |
 
     class := collector klass.
-    class sharedPools do:[:pool|
+    class theNonMetaclass sharedPools do:[:pool|
         pool theNonMetaclass classVarNames do:[:nm|
             resultSet add:(SmallSenseVariablePO classVariable: nm in: pool).
         ]
     ].
 
     "Created: / 24-07-2013 / 16:59:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 24-07-2013 / 23:19:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 addVariables
--- a/SmallSenseRecognizerTests.st	Wed Jul 24 17:06:19 2013 +0100
+++ b/SmallSenseRecognizerTests.st	Thu Jul 25 11:34:26 2013 +0100
@@ -765,3 +765,4 @@
 version_SVN
     ^ '$Id: SmallSenseRecognizerTests.st 7705 2011-04-08 09:49:06Z vranyj1 $'
 ! !
+
--- a/SmallSenseService.st	Wed Jul 24 17:06:19 2013 +0100
+++ b/SmallSenseService.st	Thu Jul 25 11:34:26 2013 +0100
@@ -12,7 +12,7 @@
 "{ Package: 'jv:smallsense' }"
 
 Tools::BackgroundSourceProcessingService subclass:#SmallSenseService
-	instanceVariableNames:'rulesHolder rules highlighter'
+	instanceVariableNames:'rulesHolder rules highlighter support'
 	classVariableNames:'Debugging'
 	poolDictionaries:''
 	category:'SmallSense-Interface'
@@ -125,6 +125,20 @@
     "Created: / 05-08-2011 / 10:59:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!SmallSenseService methodsFor:'accessing-views'!
+
+codeView
+    ^ codeView
+!
+
+gutterView
+    ^ gutterView
+!
+
+textView
+    ^ textView
+! !
+
 !SmallSenseService methodsFor:'aspects'!
 
 rulesHolder
@@ -173,6 +187,8 @@
 update:something with:aParameter from:changedObject
     "Invoked when an object that I depend upon sends a change notification."
 
+    | lang |
+
     changedObject == rulesHolder ifTrue:[
         UserPreferences current smallSenseBackgroundLintEnabled ifTrue:[
             | ruleList |
@@ -183,11 +199,29 @@
 
             self process.
         ].
+        ^ self.
+    ].
+
+    changedObject == codeView ifTrue:[
+        (#(methodHolder classHolder languageHolder) includes: something) ifTrue:[
+            aParameter key removeDependent: self.
+            aParameter key addDependent: self.                         
+        ]
+    ].
+
+    (changedObject == codeView languageHolder 
+        or:[something == codeView classHolder
+        or:[something == codeView methodHolder]]) ifTrue:[
+        support language ~~ (lang := codeView language) ifTrue:[
+            support := SmallSenseEditSupport forLanguage: lang.
+            support service: self.
+        ].
+        ^self.
     ].
 
     super update:something with:aParameter from:changedObject
 
-    "Modified: / 04-04-2012 / 13:38:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 25-07-2013 / 11:28:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !SmallSenseService methodsFor:'event handling'!
@@ -218,12 +252,12 @@
      If the method returns true, the event will not be processed
      by the view."
 
-    (view == textView and: [ key == #'CodeCompletion' ]) ifTrue: [
-        self complete. ^true
-    ].
-    ^false
+    ^support notNil 
+        ifTrue:[support keyPress: key x:x y:y in: view]
+        ifFalse:[false]
 
     "Created: / 07-03-2010 / 09:36:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 24-07-2013 / 23:28:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 viewRealized
@@ -274,80 +308,6 @@
     "Created: / 30-01-2012 / 21:06:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-complete
-    |cls 
-"/     crsrPos interval node checkedNode
-"/     char start stop selectorSoFar matchingSelectors
-    |
-
-    codeView languageHolder value == SmalltalkLanguage instance   
-        ifFalse:[^self].
-
-    cls := codeView classHolder value.
-    cls isNil ifTrue:[
-        codeView showInfo:'No class'.
-        ^ self.
-    ].
-    UserInformation handle:[:ex |
-        codeView showInfo:(ex messageText).
-        ex proceed.
-    ] do:[
-        codeView withWaitCursorDo:[
-            textView keyRelease: #Control_L x:0 y:0.
-            SmallSenseCompletionWindow openForView: codeView class: cls.
-        ]
-    ].
-    ^ self.
-
-"/
-"/    interval := self selectedInterval.
-"/    interval isEmpty ifTrue:[
-"/        crsrPos := codeView characterPositionOfCursor - 1.
-"/        char := codeView characterUnderCursor.
-"/        [crsrPos > 1 and:[char isSeparator or:['.' includes:char]]] whileTrue:[
-"/            crsrPos := crsrPos - 1.
-"/            char := codeView characterAtCharacterPosition:crsrPos.
-"/        ].
-"/        interval := crsrPos to:crsrPos.
-"/    ].
-"/
-"/    node := self findNodeForInterval:interval allowErrors:true.
-"/    [node isNil] whileTrue:[
-"/        "/ expand to the left ...
-"/        interval start > 1 ifFalse:[
-"/            self showInfo:'No parseNode found'.
-"/            ^ self.
-"/        ].
-"/        interval start:(interval start - 1).
-"/        node := self findNodeForInterval:interval allowErrors:true.
-"/    ].
-"/
-"/    node isVariable ifTrue:[
-"/        self codeCompletionForVariable:node inClass:cls.
-"/        ^ self.
-"/    ].
-"/
-"/    checkedNode := node.
-"/    [checkedNode notNil] whileTrue:[
-"/        checkedNode isMessage ifTrue:[
-"/            self codeCompletionForMessage:checkedNode inClass:cls.
-"/            ^ self
-"/        ].
-"/        checkedNode isMethod ifTrue:[
-"/            self codeCompletionForMethod:checkedNode inClass:cls.
-"/            ^ self.
-"/        ].
-"/        checkedNode := checkedNode parent.
-"/    ].
-"/
-"/    self showInfo:'Node is neither variable nor message.'.
-
-    "Modified: / 04-07-2006 / 18:48:26 / fm"
-    "Modified: / 20-11-2006 / 12:30:59 / cg"
-    "Created: / 07-03-2010 / 09:37:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 30-01-2012 / 21:18:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
 process
     "(Re)starts the processing job. Should be called whenever a source 
      must be (re)processed."
@@ -368,16 +328,17 @@
     | cls env oldCodeList oldCode |
 
     rules isNil ifTrue:[ ^ self ].
-
-    Delay waitForMilliseconds: 200."Give user some time to write"
-
+    codeView codeAspect ~~ #method ifTrue:[ ^ self ].
+    codeView language isNil ifTrue: [ ^ self ].
+    codeView language isSmalltalk ifFalse: [ ^ self ]. 
     done := false.
     modified := false.
-    codeView codeAspect ~~ #method ifTrue:[ ^ self ].
-    codeView language isNil ifTrue: [ ^ self ].
-    codeView language isSmalltalk ifFalse: [ ^ self ].
+
     cls := codeView klass.
-    cls isNil ifTrue:[^ self ].
+        cls isNil ifTrue:[^ self ].    
+
+
+    Delay waitForMilliseconds: 200."Give user some time to write"
 
     (cls notNil and:[cls isObsolete]) ifTrue:[
         cls isMeta ifTrue:[
@@ -427,6 +388,7 @@
     ]
 
     "Created: / 24-01-2012 / 12:44:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 24-07-2013 / 23:06:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 rehighlight: delayed
@@ -476,6 +438,32 @@
     "Created: / 30-01-2012 / 15:11:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!SmallSenseService methodsFor:'registering'!
+
+registerIn: aCodeView
+
+    super registerIn: aCodeView.
+    aCodeView languageHolder addDependent: self.
+    aCodeView classHolder    addDependent: self.
+    aCodeView methodHolder   addDependent: self.
+    support := SmallSenseEditSupport forLanguage: aCodeView language.
+    support service: self.
+
+    "Created: / 24-07-2013 / 23:13:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+unregister
+
+    "Uninstall myself from my codeView"
+
+    super unregister.
+    codeView languageHolder removeDependent: self.
+    codeView classHolder    removeDependent: self.
+    codeView methodHolder   removeDependent: self.
+
+    "Created: / 24-07-2013 / 23:14:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !SmallSenseService class methodsFor:'documentation'!
 
 version_HG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmallSenseSmalltalkEditSupport.st	Thu Jul 25 11:34:26 2013 +0100
@@ -0,0 +1,204 @@
+"{ Package: 'jv:smallsense' }"
+
+SmallSenseEditSupport subclass:#SmallSenseSmalltalkEditSupport
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	category:'SmallSense-Interface'
+!
+
+!SmallSenseSmalltalkEditSupport methodsFor:'accessing'!
+
+language
+    "superclass SmallSenseEditorSupport says that I am responsible to implement this method"
+
+    ^SmalltalkLanguage instance
+
+    "Modified: / 24-07-2013 / 23:46:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SmallSenseSmalltalkEditSupport methodsFor:'editing'!
+
+insertElectricBlockOpenedBy: openText closedBy: closeText
+    | line col |
+
+    textView undoableDo:[
+        textView insertStringAtCursor: (openText ? '') , Character cr , Character cr, closeText , Character cr.
+        line := textView cursorLine - 1.
+        col := textView cursorCol  + 3.
+        textView cursorLine: line col: col.
+    ].
+
+    "Created: / 25-07-2013 / 10:41:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SmallSenseSmalltalkEditSupport methodsFor:'event handling'!
+
+keyPress: key x:x y:y in: view
+
+    "Handles an event in given view (a subview of codeView).
+     If the method returns true, the event will not be processed
+     by the view."
+
+    view == textView ifFalse:[ ^ false ].
+
+    key == #'CodeCompletion'  ifTrue: [
+        self complete. 
+        ^ true
+    ].
+    key == $^ ifTrue:[
+        ^ self keyPressReturnToken
+    ].
+    key == #Return ifTrue:[
+        ^ self keyPressReturn
+    ]. 
+
+    ^ false.
+
+    "Created: / 07-03-2010 / 09:36:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 25-07-2013 / 00:12:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+keyPressReturn
+    | line tokens i t |
+
+    line := textView listAt: textView cursorLine.
+    line isNil ifTrue:[ ^ false ].
+    line := line string.
+    line size > textView cursorCol ifTrue: [ ^ false ].
+    (line indexOfAny:'[|') == 0 ifTrue:[ ^ false ].
+    i := line size.
+    [ (line at: i) isSeparator and:[i > 0] ] whileTrue:[ i := i - 1 ].
+    i == 0 ifTrue:[ ^ false ].
+    (line at: i) == $[ ifTrue:[
+        self insertElectricBlockOpenedBy: nil closedBy: ']'.
+        ^ true
+    ].
+    tokens := self tokensAtCursorLine.
+    i := tokens size.
+    t := tokens at: i.
+    t == $[ ifTrue:[
+        self insertElectricBlockOpenedBy: nil closedBy: ']'.
+        ^ true
+    ].
+    t == $| ifTrue:[
+        i := i - 1.
+        [ i > 1 and:[ (tokens at: i) == #Identifier and:[ (tokens at: i - 1) == $: ]] ] whileTrue:[ i := i - 2 ].
+        (tokens at: i) == $[ ifTrue:[
+            self insertElectricBlockOpenedBy: nil closedBy: ']'.
+            ^ true
+        ].
+
+    ].
+    ^ false.
+
+    "Created: / 25-07-2013 / 00:02:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (format): / 25-07-2013 / 11:16:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+keyPressReturnToken
+    RBFormatter spaceAfterReturnToken ifTrue:[
+        textView undoableDo:[
+            textView  insertStringAtCursor:'^ ' 
+        ].
+        ^ true
+    ].
+    ^ false
+
+    "Created: / 24-07-2013 / 23:59:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SmallSenseSmalltalkEditSupport methodsFor:'private'!
+
+complete
+    |cls 
+"/     crsrPos interval node checkedNode
+"/     char start stop selectorSoFar matchingSelectors
+    codeView |
+
+    codeView := service codeView.
+
+    cls := codeView classHolder value.
+    cls isNil ifTrue:[
+        codeView showInfo:'No class'.
+        ^ self.
+    ].
+    UserInformation handle:[:ex |
+        codeView showInfo:(ex messageText).
+        ex proceed.
+    ] do:[
+        codeView withWaitCursorDo:[
+            codeView textView keyRelease: #Control_L x:0 y:0.
+            SmallSenseCompletionWindow openForView: codeView class: cls.
+        ]
+    ].
+    ^ self.
+
+"/
+"/    interval := self selectedInterval.
+"/    interval isEmpty ifTrue:[
+"/        crsrPos := codeView characterPositionOfCursor - 1.
+"/        char := codeView characterUnderCursor.
+"/        [crsrPos > 1 and:[char isSeparator or:['.' includes:char]]] whileTrue:[
+"/            crsrPos := crsrPos - 1.
+"/            char := codeView characterAtCharacterPosition:crsrPos.
+"/        ].
+"/        interval := crsrPos to:crsrPos.
+"/    ].
+"/
+"/    node := self findNodeForInterval:interval allowErrors:true.
+"/    [node isNil] whileTrue:[
+"/        "/ expand to the left ...
+"/        interval start > 1 ifFalse:[
+"/            self showInfo:'No parseNode found'.
+"/            ^ self.
+"/        ].
+"/        interval start:(interval start - 1).
+"/        node := self findNodeForInterval:interval allowErrors:true.
+"/    ].
+"/
+"/    node isVariable ifTrue:[
+"/        self codeCompletionForVariable:node inClass:cls.
+"/        ^ self.
+"/    ].
+"/
+"/    checkedNode := node.
+"/    [checkedNode notNil] whileTrue:[
+"/        checkedNode isMessage ifTrue:[
+"/            self codeCompletionForMessage:checkedNode inClass:cls.
+"/            ^ self
+"/        ].
+"/        checkedNode isMethod ifTrue:[
+"/            self codeCompletionForMethod:checkedNode inClass:cls.
+"/            ^ self.
+"/        ].
+"/        checkedNode := checkedNode parent.
+"/    ].
+"/
+"/    self showInfo:'Node is neither variable nor message.'.
+
+    "Modified: / 04-07-2006 / 18:48:26 / fm"
+    "Modified: / 20-11-2006 / 12:30:59 / cg"
+    "Created: / 07-03-2010 / 09:37:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 24-07-2013 / 23:29:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+indentAtCursorLine
+    ^ (service textView listAt: service textView cursorLine) indexOfNonSeparator
+
+    "Created: / 25-07-2013 / 00:13:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+tokensAtCursorLine
+    | scanner token |
+
+    scanner := Scanner for: (service textView listAt: service textView cursorLine) string.
+    ^ OrderedCollection streamContents:[:tokens |
+        [ token := scanner nextToken.token ~~ #EOF ] whileTrue:[
+            tokens nextPut: token.
+        ].
+    ].
+
+    "Created: / 25-07-2013 / 00:07:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
--- a/abbrev.stc	Wed Jul 24 17:06:19 2013 +0100
+++ b/abbrev.stc	Thu Jul 25 11:34:26 2013 +0100
@@ -5,6 +5,7 @@
 SmallSenseChecker SmallSenseChecker jv:smallsense 'SmallSense-Lint' 0
 SmallSenseCompletionWindow SmallSenseCompletionWindow jv:smallsense 'SmallSense-Interface' 1
 SmallSenseCriticsWindow SmallSenseCriticsWindow jv:smallsense 'SmallSense-Interface' 1
+SmallSenseEditSupport SmallSenseEditSupport jv:smallsense 'SmallSense-Interface' 0
 SmallSenseFinderTests SmallSenseFinderTests jv:smallsense 'SmallSense-Tests' 1
 SmallSenseInfo SmallSenseInfo jv:smallsense 'SmallSense-Model' 0
 SmallSenseManager SmallSenseManager jv:smallsense 'SmallSense-Model' 0
@@ -12,11 +13,9 @@
 SmallSenseParseNodeInspector SmallSenseParseNodeInspector jv:smallsense 'SmallSense-Interface' 1
 SmallSenseParseNodeVisitor SmallSenseParseNodeVisitor jv:smallsense 'SmallSense-Core' 0
 SmallSenseParser SmallSenseParser jv:smallsense 'SmallSense-Core' 3
-SmallSenseParserTests SmallSenseParserTests jv:smallsense 'SmallSense-Tests' 1
 SmallSensePosition SmallSensePosition jv:smallsense 'SmallSense-Core' 0
 SmallSenseQuickFixer SmallSenseQuickFixer jv:smallsense 'SmallSense-Lint' 0
 SmallSenseRecognizer SmallSenseRecognizer jv:smallsense 'SmallSense-Core' 0
-SmallSenseRecognizerTests SmallSenseRecognizerTests jv:smallsense 'SmallSense-Tests' 1
 SmallSenseResultSet SmallSenseResultSet jv:smallsense 'SmallSense-Core' 0
 SmallSenseSelectorNode SmallSenseSelectorNode jv:smallsense 'SmallSense-Core' 0
 SmallSenseService SmallSenseService jv:smallsense 'SmallSense-Interface' 0
@@ -34,9 +33,13 @@
 SmallSenseClassType SmallSenseClassType jv:smallsense 'SmallSense-Types' 0
 SmallSenseConstantPO SmallSenseConstantPO jv:smallsense 'SmallSense-Interface-PO' 0
 SmallSenseFinder SmallSenseFinder jv:smallsense 'SmallSense-Core' 0
+SmallSenseGenericEditSupport SmallSenseGenericEditSupport jv:smallsense 'SmallSense-Interface' 0
 SmallSenseInferencer SmallSenseInferencer jv:smallsense 'SmallSense-Inference' 0
 SmallSenseMethodInfo SmallSenseMethodInfo jv:smallsense 'SmallSense-Model' 0
 SmallSenseMethodPO SmallSenseMethodPO jv:smallsense 'SmallSense-Interface-PO' 0
+SmallSenseParserTests SmallSenseParserTests jv:smallsense 'SmallSense-Tests' 1
+SmallSenseRecognizerTests SmallSenseRecognizerTests jv:smallsense 'SmallSense-Tests' 1
+SmallSenseSmalltalkEditSupport SmallSenseSmalltalkEditSupport jv:smallsense 'SmallSense-Interface' 0
 SmallSenseSnippetPO SmallSenseSnippetPO jv:smallsense 'SmallSense-Interface-PO' 0
 SmallSenseUnionType SmallSenseUnionType jv:smallsense 'SmallSense-Types' 0
 SmallSenseUnknownType SmallSenseUnknownType jv:smallsense 'SmallSense-Types' 1
--- a/bc.mak	Wed Jul 24 17:06:19 2013 +0100
+++ b/bc.mak	Thu Jul 25 11:34:26 2013 +0100
@@ -86,6 +86,7 @@
 $(OUTDIR)SmallSenseChecker.$(O) SmallSenseChecker.$(H): SmallSenseChecker.st $(INCLUDE_TOP)\stx\goodies\refactoryBrowser\lint\SmalllintChecker.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseCompletionWindow.$(O) SmallSenseCompletionWindow.$(H): SmallSenseCompletionWindow.st $(INCLUDE_TOP)\stx\libview2\SimpleDialog.$(H) $(INCLUDE_TOP)\stx\libview2\ApplicationModel.$(H) $(INCLUDE_TOP)\stx\libview2\Model.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseCriticsWindow.$(O) SmallSenseCriticsWindow.$(H): SmallSenseCriticsWindow.st $(INCLUDE_TOP)\stx\libview2\ApplicationModel.$(H) $(INCLUDE_TOP)\stx\libview2\Model.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)SmallSenseEditSupport.$(O) SmallSenseEditSupport.$(H): SmallSenseEditSupport.st $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseInfo.$(O) SmallSenseInfo.$(H): SmallSenseInfo.st $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseManager.$(O) SmallSenseManager.$(H): SmallSenseManager.st $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSensePO.$(O) SmallSensePO.$(H): SmallSensePO.st $(INCLUDE_TOP)\stx\libwidg2\HierarchicalItem.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
@@ -111,9 +112,11 @@
 $(OUTDIR)SmallSenseClassType.$(O) SmallSenseClassType.$(H): SmallSenseClassType.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseType.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseConstantPO.$(O) SmallSenseConstantPO.$(H): SmallSenseConstantPO.st $(INCLUDE_TOP)\jv\smallsense\SmallSensePO.$(H) $(INCLUDE_TOP)\stx\libwidg2\HierarchicalItem.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseFinder.$(O) SmallSenseFinder.$(H): SmallSenseFinder.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseParseNodeVisitor.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)SmallSenseGenericEditSupport.$(O) SmallSenseGenericEditSupport.$(H): SmallSenseGenericEditSupport.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseEditSupport.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseInferencer.$(O) SmallSenseInferencer.$(H): SmallSenseInferencer.st $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(INCLUDE_TOP)\jv\smallsense\SmallSenseParseNodeVisitor.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseMethodInfo.$(O) SmallSenseMethodInfo.$(H): SmallSenseMethodInfo.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseInfo.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseMethodPO.$(O) SmallSenseMethodPO.$(H): SmallSenseMethodPO.st $(INCLUDE_TOP)\jv\smallsense\SmallSensePO.$(H) $(INCLUDE_TOP)\stx\libwidg2\HierarchicalItem.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)SmallSenseSmalltalkEditSupport.$(O) SmallSenseSmalltalkEditSupport.$(H): SmallSenseSmalltalkEditSupport.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseEditSupport.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseSnippetPO.$(O) SmallSenseSnippetPO.$(H): SmallSenseSnippetPO.st $(INCLUDE_TOP)\jv\smallsense\SmallSensePO.$(H) $(INCLUDE_TOP)\stx\libwidg2\HierarchicalItem.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseUnionType.$(O) SmallSenseUnionType.$(H): SmallSenseUnionType.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseType.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)SmallSenseUnknownType.$(O) SmallSenseUnknownType.$(H): SmallSenseUnknownType.st $(INCLUDE_TOP)\jv\smallsense\SmallSenseType.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
--- a/jv_smallsense.st	Wed Jul 24 17:06:19 2013 +0100
+++ b/jv_smallsense.st	Thu Jul 25 11:34:26 2013 +0100
@@ -30,7 +30,7 @@
         #'stx:goodies/refactoryBrowser/helpers'    "BrowserEnvironment - superclass of SmallSenseUnacceptedMethodEnvironment "
         #'stx:goodies/refactoryBrowser/lint'    "RBLintRule - extended "
         #'stx:goodies/roeltyper'    "TypeCollector - superclass of SmallSenseTypeCollector "
-        #'stx:goodies/sunit'    "TestAsserter - superclass of SmallSenseTestCase "
+        #'stx:goodies/sunit'    "TestAsserter - superclass of SmallSenseParserTests "
         #'stx:libbasic'    "Autoload - superclass of SmallSenseBaseTestClass "
         #'stx:libbasic2'    "CacheDictionary - superclass of SmallSenseTypeCollectorCache "
         #'stx:libcomp'    "AbstractSyntaxHighlighter - superclass of SmallSenseAbstractInstvarInterfaceExtractor "
@@ -77,6 +77,7 @@
      exclude individual packages in the #excludedFromPreRequisites method."
 
     ^ #(
+        #'stx:goodies/refactoryBrowser/parser'    "RBFormatter - referenced by SmallSenseSmalltalkEditSupport>>keyPressReturnToken "
         #'stx:libbasic3'    "ChangeSet - referenced by RBTransformationRule>>fixes: "
     )
 !
@@ -105,6 +106,7 @@
         SmallSenseChecker
         SmallSenseCompletionWindow
         SmallSenseCriticsWindow
+        SmallSenseEditSupport
         (SmallSenseFinderTests autoload)
         SmallSenseInfo
         SmallSenseManager
@@ -112,11 +114,9 @@
         SmallSenseParseNodeInspector
         SmallSenseParseNodeVisitor
         SmallSenseParser
-        (SmallSenseParserTests autoload)
         SmallSensePosition
         SmallSenseQuickFixer
         SmallSenseRecognizer
-        (SmallSenseRecognizerTests autoload)
         SmallSenseResultSet
         SmallSenseSelectorNode
         SmallSenseService
@@ -134,9 +134,13 @@
         SmallSenseClassType
         SmallSenseConstantPO
         SmallSenseFinder
+        SmallSenseGenericEditSupport
         SmallSenseInferencer
         SmallSenseMethodInfo
         SmallSenseMethodPO
+        (SmallSenseParserTests autoload)
+        (SmallSenseRecognizerTests autoload)
+        SmallSenseSmalltalkEditSupport
         SmallSenseSnippetPO
         SmallSenseUnionType
         SmallSenseUnknownType
--- a/libInit.cc	Wed Jul 24 17:06:19 2013 +0100
+++ b/libInit.cc	Thu Jul 25 11:34:26 2013 +0100
@@ -30,6 +30,7 @@
 _SmallSenseChecker_Init(pass,__pRT__,snd);
 _SmallSenseCompletionWindow_Init(pass,__pRT__,snd);
 _SmallSenseCriticsWindow_Init(pass,__pRT__,snd);
+_SmallSenseEditSupport_Init(pass,__pRT__,snd);
 _SmallSenseInfo_Init(pass,__pRT__,snd);
 _SmallSenseManager_Init(pass,__pRT__,snd);
 _SmallSensePO_Init(pass,__pRT__,snd);
@@ -55,9 +56,11 @@
 _SmallSenseClassType_Init(pass,__pRT__,snd);
 _SmallSenseConstantPO_Init(pass,__pRT__,snd);
 _SmallSenseFinder_Init(pass,__pRT__,snd);
+_SmallSenseGenericEditSupport_Init(pass,__pRT__,snd);
 _SmallSenseInferencer_Init(pass,__pRT__,snd);
 _SmallSenseMethodInfo_Init(pass,__pRT__,snd);
 _SmallSenseMethodPO_Init(pass,__pRT__,snd);
+_SmallSenseSmalltalkEditSupport_Init(pass,__pRT__,snd);
 _SmallSenseSnippetPO_Init(pass,__pRT__,snd);
 _SmallSenseUnionType_Init(pass,__pRT__,snd);
 _SmallSenseUnknownType_Init(pass,__pRT__,snd);
--- a/smallsense.rc	Wed Jul 24 17:06:19 2013 +0100
+++ b/smallsense.rc	Thu Jul 25 11:34:26 2013 +0100
@@ -25,7 +25,7 @@
       VALUE "LegalCopyright", "Copyright Claus Gittinger 1988-2011\nCopyright eXept Software AG 1998-2011\0"
       VALUE "ProductName", "Smalltalk/X\0"
       VALUE "ProductVersion", "6.2.3.0\0"
-      VALUE "ProductDate", "Wed, 24 Jul 2013 15:22:55 GMT\0"
+      VALUE "ProductDate", "Thu, 25 Jul 2013 10:30:09 GMT\0"
     END
 
   END