VDBSimpleDebuggerConsoleApplication.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Wed, 23 Jan 2019 11:02:06 +0000
changeset 142 dae35d5b3d72
parent 139 c619cc458fb1
child 143 df7f89efd39d
permissions -rw-r--r--
Added (some) documentation ...albeit far from being complete, as always.

"
jv:vdb - Visual / VM Debugger
Copyright (C) 2015-now Jan Vrany

This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'

You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
"
"{ Package: 'jv:vdb' }"

"{ NameSpace: Smalltalk }"

VDBAbstractConsoleApplication subclass:#VDBSimpleDebuggerConsoleApplication
	instanceVariableNames:'consoleInput consoleOutput consoleOutputLock consoleProcess
		consolePrompt consolePromptPrinted outstandingCommand
		outstandingCommandToken outstandingCommandBlocker
		ignoreNextLogStreamEvent running'
	classVariableNames:''
	poolDictionaries:'GDBCommandStatus'
	category:'VDB-UI-Console'
!

!VDBSimpleDebuggerConsoleApplication class methodsFor:'documentation'!

copyright
"
jv:vdb - Visual / VM Debugger
Copyright (C) 2015-now Jan Vrany

This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'

You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
"
!

documentation
""
! !

!VDBSimpleDebuggerConsoleApplication class methodsFor:'accessing'!

defaultWindowTitle
    ^ self resources string: 'Debugger Console'

    "Created: / 08-01-2018 / 18:59:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 03-10-2018 / 15:39:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication class methodsFor:'startup-web applications'!

initialPageSpec
    "this is only required for web-applications"

    ^ self shouldImplement
!

pageSpecs
    "this is only required for web-applications"

    ^ self shouldImplement
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'accessing'!

consoleInput
    ^ consoleInput

    "Created: / 21-01-2019 / 14:18:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

consoleOutput
    ^ consoleOutput

    "Created: / 21-01-2019 / 14:18:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'actions'!

doComplete: line
    "Called when a user triggers a command completion (usually by pressing
     tab)"

    | command |

    command := GDBMI_complete arguments: (Array with: line).
    debugger send: command andWithResultDo: [ :result |
        consoleView sensor pushUserEvent: #doComplete:with: for: self withArguments: (Array with: line with: result)
    ].

    "Created: / 30-12-2018 / 22:01:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (comment): / 31-12-2018 / 11:35:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

doComplete: line with: result
    "Called asynchronously from #doComplete: when possible completions
     are computed.

     Private, this is for private use by #doComplete: 
    "
    self consoleView completeCommandWith: (result propertyAt: #completions).

    "Created: / 30-12-2018 / 22:04:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-01-2019 / 14:24:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'aspects'!

consoleViewClass
    ^ VDBSimpleDebuggerConsoleView

    "Modified: / 21-01-2019 / 14:22:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'event handling'!

onCmdParamChanged: event
    event name = 'prompt' ifTrue:[
        consolePrompt := event value
    ].

    "Created: / 19-01-2019 / 22:13:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onCommandEvent: event
    event command == outstandingCommand ifTrue:[ 
        outstandingCommandToken := event token.
        ignoreNextLogStreamEvent := true.
    ].

    "Created: / 06-06-2014 / 22:43:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 11-06-2014 / 12:35:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onCommandResultEvent: event
    outstandingCommandToken notNil ifTrue:[ 
        event token == outstandingCommandToken ifTrue:[ 
            "/ Check if command ended up with an error. If so,
            "/ print the error message.
            event result status == CommandStatusError ifTrue:[ 
                self showCR: ('Error: %1 ' bindWith: (event result propertyAt: #msg)).
            ] ifFalse:[
                "/ Check if the command issues is actually a MI command,
                "/ if so, print "Done" to the console since MI command don't
                "/ provide user feedback.
                outstandingCommand isMICommand ifTrue:[ 
                    self showCR: ('Done ( %1 , see even log for result value)' bindWith: outstandingCommand value)
                ].
            ].
            outstandingCommand := outstandingCommandToken := nil. 
            outstandingCommandBlocker signalForAll.     
        ].
    ].

    "Created: / 06-06-2014 / 22:44:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 27-02-2015 / 13:01:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onEventSetProcessingFinished: event
    self showPrompt.

    "Created: / 18-09-2014 / 23:11:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onLogOutputEvent: event
    ignoreNextLogStreamEvent ifTrue:[ 
        ignoreNextLogStreamEvent := false.
    ] ifFalse:[
        self onStreamOutputEvent: event  
    ]

    "Created: / 11-06-2014 / 12:37:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 04-04-2018 / 22:50:14 / jv"
    "Modified: / 30-12-2018 / 22:03:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onRunningEvent: event
    running := true.
    consoleView readOnly: true.

    "Created: / 19-01-2019 / 23:46:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onStoppedEvent: event
    running := false.
    consoleView readOnly: false.
    self showPrompt.

    "Created: / 19-01-2019 / 23:46:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

onStreamOutputEvent: event
    consolePromptPrinted ifTrue:[ self showCR:'' ].
    consolePromptPrinted := false.
    event value asStringCollection do:[:line |  
        line notEmptyOrNil ifTrue:[ 
            self showCR: line.  
        ].
    ].

    "Created: / 11-06-2014 / 12:00:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 30-12-2018 / 22:02:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'hooks'!

commonPostOpen
    consoleProcess isNil ifTrue:[
        consoleProcess := 
            [
                [ self consoleProcess1Command ] loop. 
            ] newProcess.
        consoleProcess name: 'VDB Debugger Console REPL loop'.
        consoleProcess resume.
    ].

    "Created: / 10-06-2014 / 01:25:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 19-01-2019 / 23:48:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

postBuildConsoleView: aTextCollector
    consoleView := aTextCollector scrolledView.
    consoleView readOnly: true;       
                font: CodeView defaultFont;
                foregroundColor: Color white
                backgroundColor: Color black;
                cursorForegroundColor: Color white
                      backgroundColor: Color white.

    "Modified: / 08-01-2018 / 19:16:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'initialization & release'!

initialize
    super initialize.

    consoleInput := GDBInternalPipeStream new.
    consoleOutput := GDBInternalPipeStream new.
    consoleOutputLock := RecursionLock new.
    consolePrompt := '(gdb) '.
    consolePromptPrinted := false.
    running := false.
    outstandingCommandBlocker := Semaphore new.
    ignoreNextLogStreamEvent := false.

    "Created: / 10-06-2014 / 01:23:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 07-04-2018 / 23:13:27 / jv"
    "Modified: / 21-01-2019 / 15:37:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

initializeConsoleView: aTerminalView
    super initializeConsoleView: aTerminalView.
    aTerminalView localEcho:true.
    aTerminalView inputTranslateCRToNL:true.
    aTerminalView lineEditMode:true.

    "Created: / 21-01-2019 / 14:13:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 21-01-2019 / 15:33:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

initializeConsoleView: aTerminalView forDebugger: aGDBDebugger
    super initializeConsoleView: aTerminalView forDebugger: aGDBDebugger.
    (aGDBDebugger notNil and:[aGDBDebugger hasCommand:'-complete']) ifTrue:[ 
        consoleView completionBlock: [ :prefix | self doComplete: prefix ].
        consolePrompt := debugger getParameter: 'prompt'.
    ] ifFalse:[ 
        consoleView completionBlock: nil.
        consolePrompt := '(gdb) '
    ].

    "Created: / 21-01-2019 / 15:33:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 21-01-2019 / 17:49:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

release
    super release.
    consoleProcess terminate.

    "Created: / 10-06-2014 / 01:34:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

subscribe   
    "Register for debugger events. To be overrided by subclasses"

    super subscribe.
    debugger announcer 
        when: GDBCommandEvent           send: #onCommandEvent:          to: self;
        when: GDBCommandResultEvent     send: #onCommandResultEvent:    to: self;

        when: GDBRunningEvent           send: #onRunningEvent:          to: self;
        when: GDBStoppedEvent           send: #onStoppedEvent:          to: self;

        when: GDBConsoleOutputEvent      send: #onStreamOutputEvent:     to: self;
        when: GDBTargetOutputEvent       send: #onStreamOutputEvent:     to: self;
        when: GDBLogOutputEvent          send: #onLogOutputEvent:        to: self;

        when: GDBEventSetProcessingFinished send: #onEventSetProcessingFinished: to: self;

        when: GDBCmdParamChangedEvent send: #onCmdParamChanged: to: self.

    running := debugger inferiors anySatisfy:[ :tg | tg isRunning ].

    "Created: / 06-06-2014 / 21:26:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 21-01-2019 / 15:37:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'private - console process'!

consoleProcess1Command
    | cmdLine cmd |

    self showPrompt.
    cmdLine := consoleInput nextLine asString.
    self showCR.
    consolePromptPrinted := false.
    cmdLine notEmptyOrNil ifTrue:[
        cmd := GDBCommand parse: cmdLine.
        cmd isCLICommand ifTrue:[ 
            cmd runOnBackground: true.  
        ].
        outstandingCommand := cmd.
        consoleView readOnly:true.  
        debugger send:cmd andWait:false. 
        outstandingCommandBlocker wait.
        consoleView readOnly:false.
    ].

    "Created: / 19-01-2019 / 23:49:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 21-01-2019 / 12:25:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication methodsFor:'private - writing'!

show: aString
    consoleOutputLock critical:[ 
        consoleOutput nextPutAll: aString.
    ].

    "Created: / 11-06-2014 / 08:02:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 11-06-2014 / 11:53:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

showCR
    consoleOutputLock critical:[ 
        consoleOutput crlf.
    ].

    "Created: / 21-01-2019 / 12:25:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

showCR: aString
    consoleOutputLock critical:[ 
        consoleOutput nextPutAll: aString; crlf.
    ].

    "Created: / 11-06-2014 / 08:02:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 16-01-2019 / 10:52:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

showPrompt
    (running not and: [consolePromptPrinted not]) ifTrue:[
        self show: consolePrompt.
        consolePromptPrinted := true.
    ].

    "Created: / 18-09-2014 / 23:18:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 04-04-2018 / 23:01:24 / jv"
    "Modified: / 19-01-2019 / 23:58:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBSimpleDebuggerConsoleApplication class methodsFor:'documentation'!

version_HG

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