- live browsing of Self object memory -

lobby traitsprompt

CopyDowns: vector

CreatorPath: traits prompt

Module: prompt

parent* = traits clonable
evalInput:CanContinue:NeedToContinue: =
( | historyEntry. res |
    historyEntry: history addCmd: s.
    res: s evalInContext: receiver 
                FileName: '<the prompt>'
      IfFail: [ | :err |
          err prematureEOF ifTrue: [
             "canContinue && ['prematureEndOfInput' isPrefixOf: e]"
             "Avoid having multiline commands take up >1 history entries."
              history removeEntry: historyEntry. 
              need needToContinue: true. 
              ^ self.
          ] False: [| spaces |
              (('' padOnRight:
                (regularPrompt: history nextID pred) size +
                  err start x )
               , '^ ', err printString) printLine.
              process this abort.
          ] 
      ].
    historyEntry result: res.
    showResult: res)
inputLoop =
( | input <- '' |
    inputLoopProcess: process this.
    stopping:        false.
    waitingForInput: false.
    continuing:      false.
    stdin reset.
    stdout reset.
    [stopping] whileFalse: [ | newInput <- ''. |
        waitingForInput: true.
        printPrompt.
        newInput: stdin readLine.
        waitingForInput: false.
        input: input, newInput.
        stdin atEOF ifTrue: [
            stdin resetEOF.
            input isEmpty ifTrue: ['\n' print. ^ self].
            '\n' print. 
            input: ''.
            continuing: false.
        ] False: [
            input: (processInput: input).
        ].
    ].
    'stopping' printLine.
    scheduler stop.
    self)
mainInputLoop =
( 
    inputLoop.
    scheduler stop)
notify = ( waitingForInput ifTrue: [ printPrompt ])
quit = ( stopping: true)
receiver = ( reflect: shell)
start = ( scheduler start)
printPrompt =
( 
    continuing ifTrue: [ printContinuationPrompt: history nextID ]
                False: [ printRegularPrompt: history nextID ])
processInput: =
( | async <- false. input <- ''. msg. needToContinue. p |
    input: inp.
    input isAllWhiteSpace ifTrue: [^ ''].
    input: (handleSpecialInput: input AsyncBlk: [async: true]).
    needToContinue: (| parent* = traits clonable.
                       needToContinue <- false |) copy.
    msg: (message copy receiver: self
                       Selector: 'evalInput:CanContinue:NeedToContinue:'
                           With: input
                           With: async not
                           With: needToContinue).
    p: (process copySend: msg).
    p causeOfBirth: input.
    p resume.
    async ifTrue: [
        p objectID printLine.
        continuing: false.
        ^ ''.  " can't continue input past & "
    ].
    p waitForSuspension.
    continuing: needToContinue needToContinue.
    continuing ifTrue: [
         input: input, '\n'.
    ] False: [
         input: ''.
         updateUI ifTrue: [ui update].
    ].
    input)
showResult: = ( (reflect: res) name printLine. self)

promptPrinting

continuationPrompt: = ( (continuationPromptPrefix: n), continuationPromptSuffix)
continuationPromptPrefix: =
( | ws |
    ws: ((regularPrompt: n) size - continuationPromptSuffix size)
        max: 0.
    '' padOnLeft: ws)
continuationPromptSuffix = '>> '
printContinuationPrompt: = ( (continuationPrompt: n) print. self)
printRegularPrompt: = ( (regularPrompt: n) print. self)
promptHistory: = ( ' ', n printString)
promptPrefix = '\"Self'
promptSuffix = '\" '
regularPrompt: = ( promptPrefix, (promptHistory: n), promptSuffix)

special input

applyModifier:To:IfFail: =
( | n <- 0. res <- ''. s1 <- ''. s2 <- '' |
    '^' != mod first ifTrue: [^ errBlk value].
    s1: (mod copyFrom: 1).  "Skip the '^'."
    n: (s1 keyOf: '^' IfAbsent: -1).
    -1 != n ifTrue: [
        s2: (s1 copyFrom: 1 + n).
        s1: (s1 copySize: n).
    ].
    insert: s1 InsteadOf: s2 In: cmd IfNoMatch: errBlk)
echoCommand: =
( 
    '"' print. cmd print. '"' printLine.
    self)
getPreviousCommand = ( (history get: (history nextID - 1)) command)
handleSpecialInput:AsyncBlk: =
( | echo <- false. input <- ''. input2 <- '' |
    input: inp.
    preferences useAmpersandToBackground && ['&' = input last] ifTrue: [
        asyncBlk value.
        input: input copyWithoutLast.
    ].
    input2: input shrinkwrapped.
    ('!!' isPrefixOf: input2) ifTrue: [
        echo: true.
        input: getPreviousCommand.
        2 < input2 size ifTrue: [input: input, (input2 copyFrom: 2)].
    ] False: [
    '^' = input2 first ifTrue: [
        echo: true.
        input: (applyModifier: input2 To: getPreviousCommand IfFail: [
            'Modifier failed' printLine.
            echo: false.
            '0'.   "Safe string to evaluate."
         ]).
    ] False: [
    '!' = input2 first ifTrue: [| str1 <- ''. n <- 0. |
        str1: (input2 copyFrom: 1).
        n: (str1 asIntegerIfFail: nil).
        n ifNil: [   "Not !number, so must be !prefix."
            input: 'history executePrefix: \'', str1, '\''.
        ] IfNotNil: [
            input: 'history execute: ', n printString.
        ].
    ]]].
    echo ifTrue: [echoCommand: input].
    input)
insert:InsteadOf:In:IfNoMatch: =
( 
    1 + (str size - s1 size) do: [|:i|
        (s1 isPrefixOf: (str copyFrom: i)) ifTrue: [
            ^ (str copySize: i), s2, (str copyFrom: i + s1 size).
        ].
    ].
    noMatchBlk value)

suspending

suspendWhile: =
( | t |
    inputLoopProcess suspend. stdin reset. t: b value. stdin reset. inputLoopProcess resume. printPrompt. t)
The prompt interferes with other REPL like users of stdin/stdout. To avoid this, wrap your REPL in a block and use this method to temporarily suspend the prompt loop.
dummyInputLoopProcess = traits prompt dummyInputLoopProcess