Tools__CodeHighlightingService.st
author Claus Gittinger <cg@exept.de>
Fri, 27 Jul 2012 23:51:55 +0200
changeset 11705 6f107a6cac2d
parent 11617 20c6592bdc20
child 12099 d3315fdc1c92
permissions -rw-r--r--
changed: #process: fixed some (but not all) missing codeAspect settings

"
 COPYRIGHT (c) 2010 by Jan Vrany, SWING Research Group. CTU in Prague
	      All Rights Reserved

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the 'Software'), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"
"{ Package: 'stx:libtool' }"

"{ NameSpace: Tools }"

BackgroundSourceProcessingService subclass:#CodeHighlightingService
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-CodeView'
!

!CodeHighlightingService class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2010 by Jan Vrany, SWING Research Group. CTU in Prague
	      All Rights Reserved

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the 'Software'), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"
! !

!CodeHighlightingService class methodsFor:'accessing'!

label

    "Answers short label - for UI"

    ^'Syntax Highlighting'

    "Created: / 07-03-2010 / 14:00:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!CodeHighlightingService methodsFor:'accessing'!

syntaxHighlighter
    | app lang highlighter |

    "First, ask application..."
    app := codeView application.
    app notNil ifTrue:[
        | mthd class |

        mthd := codeView methodHolder value.
        (mthd notNil and:[app respondsTo: #syntaxHighlighterForMethod:]) ifTrue:[
            highlighter := app syntaxHighlighterForMethod:mthd.
        ] ifFalse:[
            class := codeView classHolder value.
            (class notNil and:[app respondsTo: #syntaxHighlighterForClass:]) ifTrue:[                        
                highlighter := app syntaxHighlighterForClass: class.
            ] ifFalse:[
                (class notNil and:[app respondsTo: #syntaxHighlighter]) ifTrue:[                        
                    highlighter := app syntaxHighlighterClass.
                ].
            ].
        ]
    ].
    "App did not provide any highlighter..."
    highlighter isNil ifTrue:[        
        highlighter := (lang := codeView language) isNil
                        ifTrue:[nil]
                        ifFalse:[lang syntaxHighlighterClass].
    ].
    "HACK!!!!!!"
    highlighter == SyntaxHighlighter ifTrue:[
        highlighter := SyntaxHighlighter2
    ].
    ^ highlighter

    "Created: / 05-08-2011 / 10:48:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 28-09-2011 / 00:23:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 19-07-2012 / 13:03:21 / cg"
!

syntaxHighlighters

    | highlighters |

    highlighters := OrderedCollection new: 4.

    codeView services do:[:service|
        | highlighter |
        highlighter := service syntaxHighlighter.        
        highlighter notNil ifTrue:[
            "HACK, since AbstractSyntaxHighlighter overwrite
             emphasis instead of adding it..."
            (highlighter isKindOf: AbstractSyntaxHighlighter class) ifTrue:[
                highlighters addFirst: highlighter                    
            ] ifFalse:[
                highlighters add: highlighter
            ].
        ]
    ].
    ^highlighters

    "Created: / 05-08-2011 / 10:49:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 19-07-2012 / 12:58:48 / cg"
! !

!CodeHighlightingService methodsFor:'acessing-defaults'!

defaultJobName

    ^'CodeView2''s syntax highlighting job'

    "Created: / 24-01-2012 / 12:06:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!CodeHighlightingService methodsFor:'private'!

process
    "(Re)starts the processing job. Should be called whenever a source 
     must be (re)processed."

    | highlighters |

    (highlighters := self syntaxHighlighters) isEmptyOrNil ifTrue:[
        "No higlighter, nothing to do"
        ^self
    ].

    super process.

    "Modified: / 07-07-2011 / 12:26:12 / Jan Vrany <jan.vrant@fit.cvut,cz>"
    "Modified: / 26-09-2011 / 15:40:23 / cg"
    "Created: / 24-01-2012 / 12:11:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

process: delayed

    |oldCode oldCodeList newCode elements cls mthd highlighterClasses|

codeView topView class == DebugView ifTrue:[^ self].

    done := false.
    modified := false.
    codeView syntaxElements: nil.
    codeView syntaxElementSelection: nil.

    highlighterClasses := self syntaxHighlighters.

    cls := codeView klass.
    (cls notNil and:[cls isObsolete]) ifTrue:[
        cls isMeta ifTrue:[
            cls := (Smalltalk at:cls theNonMetaclass name) class
        ] ifFalse:[
            cls := Smalltalk at:cls name
        ].
    ].
    mthd := codeView methodHolder value.

    "textView" modified ifFalse:[
        oldCodeList := textView list copy.
        "textView" modified ifFalse:[
            oldCodeList isNil ifFalse:[
                oldCode := oldCodeList asStringWithoutEmphasis.
                "textView" modified ifFalse:[
                    Screen currentScreenQuerySignal answer:codeView device
                    do:[
                        Parser::ParseError handle:[:ex |
                            |errMsg|

                            errMsg := ex description asStringCollection first asString.

                            "/ Transcript topView raiseDeiconified.
                            "/ Transcript showCR:'ParseError: ', ex description.
"/ self halt.
                            "/ self showInfo:(errMsg colorizeAllWith:Color red).
                            newCode := nil.
                        ] do:[
                            |codeAspect|

                            elements := SortedCollection new.
                            newCode := oldCode asText.
                            codeAspect := codeView codeAspect.
                            codeAspect == SyntaxHighlighter codeAspectMethod ifTrue:[
                                highlighterClasses do:[:e|newCode := e formatMethod:mthd source:newCode in:cls using: nil elementsInto: elements].
                            ] ifFalse:[
                                codeAspect == (SyntaxHighlighter codeAspectExpression) ifTrue:[
                                    highlighterClasses do:[:e|newCode := e formatExpression:newCode in:cls elementsInto: elements].
                                ] ifFalse:[
                                    codeAspect == (SyntaxHighlighter codeAspectClassDefinition) ifTrue:[
                                        highlighterClasses do:[:e|newCode := e formatClassDefinition:newCode string in:cls elementsInto: elements].
                                    ]
                                ].
                            ].
                        ]
                    ].
                    newCode notNil ifTrue:[
                        "textView" modified ifFalse:[
                            newCode ~= oldCodeList ifTrue:[
                                newCode := newCode asStringCollection.
                                "textView" modified ifFalse:[
                                    done := true.
                                    textView notNil ifTrue:[
                                        "/ must add this event - and not been interrupted
                                        "/ by any arriving key-event.
                                        "/ self showInfo:nil.
                                        delayed ifTrue:[
                                            codeView sensor
                                                pushUserEvent:#setHighlightedCode:elements:
                                                for:self
                                                withArguments:(Array with:newCode with: elements).
                                                "/self delayedUpdateBufferLabelWithCheckIfModified
                                        ] ifFalse:[
                                            textView contents: newCode.
                                        ]
                                    ]
                                ]
                            ].
                        ]
                    ]
                ]
            ]
        ]
    ]

    "Modified: / 16-09-2011 / 17:01:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Created: / 24-01-2012 / 12:21:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 27-07-2012 / 22:23:16 / cg"
!

setHighlightedCode:newCode elements: elements
    "the background synhighlighter has generated new colored text,
     with highlighted syntax.
     If there have been no modifications in the meantime, install it."

    |firstShown lastShown cursorWasOn anyChange newLines l replaceAction list|

    "textView" modified ifTrue:[
        "/ new input arrived in the meantime

        ^ self
    ].
    done ifFalse:[
        "/ another coloring process has already been started.
        "/ ignore this (leftover) code.
        ^ self
    ].

    firstShown := textView firstLineShown.
    lastShown := textView lastLineShown.

    replaceAction := [:lNr :line |
            |oldLine|

            oldLine :=  list at:lNr ifAbsent:nil.
            oldLine notNil ifTrue:[
                line notNil ifTrue:[
                    "/ this check is needed - there is a race
                    "/ when the text is converted. This detects the
                    "/ resulting error.
                    "/ Certainly a kludge.

                    oldLine string = line string ifTrue:[
                        oldLine emphasis ~= line emphasis ifTrue:[
                            textView modifiedChannel removeDependent:self.
                            list at:lNr put:line.
                            textView modifiedChannel addDependent:self.
                            (lNr between:firstShown and:lastShown) ifTrue:[
                                anyChange ifFalse:[
                                    anyChange := true.
                                    cursorWasOn := textView hideCursor
                                ].
                                textView redrawLine:lNr
                            ]
                        ]
                    ]
                ]
            ]
        ].

    anyChange := false.
    newLines := newCode asStringCollection.
    list := textView list.
    list isNil ifTrue:[
        textView list:newLines.
    ] ifFalse:[
        "/ the cursor line first - that's where your eyes are ...
        (l := textView cursorLine) notNil ifTrue:[
            l <= newLines size ifTrue:[
                replaceAction value:l value:(newLines at:l)
            ]
        ].
        newLines keysAndValuesDo:replaceAction.
        anyChange ifTrue:[
            cursorWasOn ifTrue:[
                textView showCursor
            ]
        ]
    ].
    codeView syntaxElements: elements

    "Modified: / 09-10-2006 / 11:50:17 / cg"
    "Created: / 14-02-2010 / 16:10:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-09-2011 / 17:33:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 19-07-2012 / 12:07:05 / cg"
! !

!CodeHighlightingService class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/Tools__CodeHighlightingService.st,v 1.35 2012-07-27 21:51:55 cg Exp $'
!

version_CVS
    ^ '$Header: /cvs/stx/stx/libtool/Tools__CodeHighlightingService.st,v 1.35 2012-07-27 21:51:55 cg Exp $'
!

version_SVN
    ^ '§Id: Tools__CodeHighlightingService.st 7715 2011-04-10 16:32:58Z vranyj1 §'
! !