SmallSense__JavaEditSupport.st
author Claus Gittinger <cg@exept.de>
Mon, 15 Jul 2019 15:33:58 +0200
branchcvs_MAIN
changeset 1091 8c18b8f6ff0c
parent 944 82d17f0bad72
child 1107 f71b375b75cb
permissions -rw-r--r--
#OTHER by cg unneeded subProjects method removed (already inherited)

"
stx:goodies/smallsense - A productivity plugin for Smalltalk/X IDE
Copyright (C) 2013-2014 Jan Vrany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"
"{ Package: 'stx:goodies/smallsense' }"

"{ NameSpace: SmallSense }"

EditSupport subclass:#JavaEditSupport
	instanceVariableNames:'lastTypedKey0 lastTypedKey1 lastTypedKey2 lastTypedKey3'
	classVariableNames:''
	poolDictionaries:''
	category:'SmallSense-Java'
!

!JavaEditSupport class methodsFor:'documentation'!

copyright
"
stx:goodies/smallsense - A productivity plugin for Smalltalk/X IDE
Copyright (C) 2013-2014 Jan Vrany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"
! !

!JavaEditSupport methodsFor:'accessing'!

language
    "superclass SmallSenseEditSupport says that I am responsible to implement this method"

    | javaLanguageClass |

    javaLanguageClass := Smalltalk at:#JavaLanguage.
    ^ javaLanguageClass notNil ifTrue:[ javaLanguageClass instance ] ifFalse: [ nil ].

    "Modified: / 04-10-2013 / 08:42:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaEditSupport methodsFor:'accessing-classes'!

completionEngineClass
    "Returns a code completion engine class or nil, 
     if no completion is supported"

    UserPreferences current useJavaCompletionEngineSimple ifTrue:[
        ^ SmallSense::JavaCompletionEngineSimple
    ].
    ^ SmallSense::JavaCompletionEngine

    "Created: / 03-10-2013 / 17:45:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-08-2014 / 10:53:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

scannerClass
    "Returns a class to use for scanning lines. If nil, scanning is
     not supported and scanLine* methods will return an empty array."

    ^ (Smalltalk at: #JavaScanner)

    "Created: / 22-10-2013 / 00:38:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaEditSupport methodsFor:'editing'!

electricInsertSnippet
    | tokens  lastToken0 |

    tokens := self scanLineAtCursor.
    tokens isEmptyOrNil ifTrue:[
        ^ false
    ].
    lastToken0 := tokens at:(tokens size - 3).
    lastToken0 = 'Error' ifTrue:[
        ^ false
    ].
    (tokens last > service textView cursorCol) ifTrue:[
        ^ false
    ].
    
    "/ Insert try { ... }
    
    lastToken0 == #try ifTrue:[
        (tokens size == 4 
            or:[ (tokens size > 4) and:[ (tokens at:tokens size - 7) ~~ $. ] ]) 
                ifTrue:[
                    self electricInsertBlockOpenedBy:' {' closedBy:'}'.
                    ^ true.
                ]
    ].
    
    "/ Insert catch (  ) { ... }
    
    lastToken0 == #catch ifTrue:[
        (tokens size > 4 and:[ (tokens at:tokens size - 7) == $} ]) ifTrue:[
            | cursorLine  cursorCol |

            cursorLine := service textView cursorLine.
            cursorCol := service textView cursorCol.
            self electricInsertBlockOpenedBy:' (  ) {' closedBy:'}'.
            service textView cursorLine:cursorLine col:cursorCol + 3.
            ^ true.
        ].
    ].
    
    "/ Insert finally { ... }
    
    lastToken0 == #finally ifTrue:[
        (tokens size > 4 and:[ (tokens at:tokens size - 7) == $} ]) ifTrue:[
            self electricInsertBlockOpenedBy:' {' closedBy:'}'.
            ^ true.
        ].
    ].
    
    "/ Insert if/while/synchronized ( )  { ... }
    
    (#( #if #while #synchronized ) includes:lastToken0) ifTrue:[
        (tokens size = 4) ifTrue:[
            | cursorLine  cursorCol |

            cursorLine := service textView cursorLine.
            cursorCol := service textView cursorCol.
            self electricInsertBlockOpenedBy:' (  ) {' closedBy:'}'.
            service textView cursorLine:cursorLine col:cursorCol + 3.
            ^ true.
        ].
    ].
    
    "/ Insert for ( ; ; )  { ... }
    
    (lastToken0 == #for) ifTrue:[
        (tokens size = 4) ifTrue:[
            | cursorLine  cursorCol |

            cursorLine := service textView cursorLine.
            cursorCol := service textView cursorCol.
            self electricInsertBlockOpenedBy:' ( ; ; ) {' closedBy:'}'.
            service textView cursorLine:cursorLine col:cursorCol + 3.
            ^ true.
        ].
    ].
    ^ false

    "Created: / 22-10-2013 / 01:53:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaEditSupport 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 ifTrue:[ ^ false ].

    (self keyPressIgnored: key) ifTrue:[
        ^ true.
    ]. 

    lastTypedKey3 := lastTypedKey2.
    lastTypedKey2 := lastTypedKey1.
    lastTypedKey1 := lastTypedKey0.
    lastTypedKey0 := key.

    key == #CodeCompletion ifTrue:[ 
        | controller |

        (controller := self textView completionSupport) notNil ifTrue:[
            ^ controller handleKeyPress:key x:x y:y 
        ].
        ^ false
    ]. 

    key == #Return ifTrue:[ 
        ^ self keyPressReturn.
    ]. 

    key == ${ ifTrue:[
        ^ self keyPressOpenCurly
    ].

    key == Character space ifTrue:[
        ^ self electricInsertSnippet
    ].

    ^ false

    "Created: / 07-03-2010 / 09:36:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 13-08-2014 / 15:30:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

keyPressOpenCurly
    | line tokens i |

    line := service codeView listAt: service codeView cursorLine.
    line notEmptyOrNil ifTrue:[
        i := line size.
        [ i > 0 and:[(line at: i) isSeparator] ] whileTrue:[ i := i - 1 ].
        (i ~~ 0 and:[service codeView cursorCol < i]) ifTrue:[
            ^ false.        ].
    ] ifFalse:[
        self electricInsertBlockOpenedBy:'{' closedBy:'}'. 
        ^ true
    ].

    tokens := self scanLineAtCursor.
    tokens notEmptyOrNil ifTrue:[
        | column |

        column := service textView cursorCol.
        (tokens at: tokens size - 3) = 'Error' ifTrue:[ ^ false ].
        1 to: tokens size - 3 by: 4 do:[:i |
            (column between: (tokens at: i + 2) and: (tokens at: i + 3)) ifTrue:[
                (tokens at: i) == #String ifTrue:[ ^ false ].

                self electricInsertBlockOpenedBy:'{' closedBy:'}'. 
                ^ true.
            ].
        ].
    ].

    self electricInsertBlockOpenedBy:'{' closedBy:'}'. 
    ^ true

    "Created: / 04-08-2013 / 01:54:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 25-10-2013 / 18:03:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

keyPressReturn
    | line c i indent lineNr ccontroler  |

    textView isInInsertMode ifFalse:[ ^ false ].
    ccontroler := textView completionSupport.
    (ccontroler notNil and:[ ccontroler isCompletionViewShown ]) ifTrue:[ 
        ^ false.
    ].

    "/ First, check if the cursor is at the end of line, i.e., if
    "/ there's no text after the cursor...
    lineNr := textView cursorLine.
    line := textView list at: lineNr.
    i := line size.
    [ i > 0 and:[ (c := line at:i) isSeparator ] ] whileTrue:[ i := i - 1 ].    
    i <= textView cursorCol ifFalse:[ 
        "/ If not, do not indent...
        ^ false 
    ].

    "/ Search for closest non-empty line above
    lineNr := textView cursorLine.
    [ (line := textView list at: lineNr) isEmptyOrNil and:[lineNr > 0 ] ] whileTrue:[ lineNr := lineNr - 1 ].
    lineNr == 0 ifTrue:[ 
        "/ No such line found, givin up
        ^ false.
    ].
    indent := line indexOfNonSeparator.
    "/ Look for opening curly, if found, increase indent...
    i := line size.
    [ i > 0 and:[ (c := line at:i) isSeparator ] ] whileTrue:[ i := i - 1 ].
    (i > 0 and:[ c == ${ ]) ifTrue:[ 
        indent := indent + 4.
    ].
    textView undoableDo:[
        textView insertCharAtCursor:(Character cr).
        textView cursorCol: indent.
    ].
    ^ true

    "Created: / 13-08-2014 / 15:30:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 13-08-2014 / 20:38:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaEditSupport methodsFor:'initialization'!

initializeForService: anEditService    
    super initializeForService: anEditService.
    service textView  autoIndent:true.

    "Created: / 27-09-2013 / 13:55:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaEditSupport methodsFor:'private'!

tokenAtCursorLine
    | scanner token |

    scanner := (Smalltalk at:#JavaScanner) for: (service textView listAt: service textView cursorLine) string.

    [ 
        [ 
            token := scanner nextToken.
            (token ~~ #EOF and:[ scanner tokenEndPosition + 1 < service textView cursorCol ])
        ] whileTrue.
    ] on: Error do:[
        token := nil.
    ].
    ^ token

    "Created: / 04-08-2013 / 02:00:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 04-08-2013 / 03:10:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

tokensAtCursorLine
    | scanner token |

    scanner := (Smalltalk at:#JavaScanner) for: (service textView listAt: service textView cursorLine) string.
    ^ OrderedCollection streamContents:[:tokens |
        [ token := scanner nextToken.token ~~ #EOF ] whileTrue:[
            tokens nextPut: token.
        ].
    ].

    "Created: / 04-08-2013 / 01:57:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaEditSupport class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
!

version_HG

    ^ '$Changeset: <not expanded> $'
! !