{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE NamedFieldPuns #-}

module Ghcitui.Brick.InterpWindowEvents
    ( handleInterpreterEvent
    , handleInterpWindowPostCb
    ) where

import qualified Brick.BChan as B
import qualified Brick.Main as B
import qualified Brick.Types as B
import qualified Brick.Widgets.Edit as BE
import Control.Error (atDef, lastDef)
import Control.Monad.IO.Class (MonadIO (..))
import qualified Data.Text as T
import qualified Data.Text.Zipper as T
import qualified Graphics.Vty as V
import Lens.Micro ((^.))
import qualified Lens.Micro as Lens

import qualified Ghcitui.Brick.AppInterpState as AIS
import Ghcitui.Brick.AppState as AppState
import Ghcitui.Brick.AppTopLevel
    ( AppName (..)
    , CustomAppEvent (..)
    )
import Ghcitui.Brick.EventUtils
    ( commonPrefixes
    , reflowText
    )
import qualified Ghcitui.Ghcid.Daemon as Daemon
import Ghcitui.Util (showT)

-- -------------------------------------------------------------------------------------------------
-- Interpreter Event Handling
-- -------------------------------------------------------------------------------------------------

-- | Handle events when the interpreter (live GHCi/REPL) is selected.
handleInterpreterEvent :: B.BrickEvent AppName e -> B.EventM AppName (AppState AppName) ()
handleInterpreterEvent :: forall e.
BrickEvent AppName e -> EventM AppName (AppState AppName) ()
handleInterpreterEvent BrickEvent AppName e
ev = do
    AppState AppName
appState <- EventM AppName (AppState AppName) (AppState AppName)
forall s (m :: * -> *). MonadState s m => m s
B.get
    case BrickEvent AppName e
ev of
        B.VtyEvent (V.EvKey Key
V.KEnter []) -> do
            let cmd :: Text
cmd = Text -> Text
T.strip (AppEventCompletions -> Text
T.unlines (AppState AppName -> AppEventCompletions
forall {n}. AppState n -> AppEventCompletions
editorContents AppState AppName
appState))
            let finishedState :: AppState AppName
finishedState = AppState AppName
appState{waitingOnRepl = False}
            let callback :: Either DaemonError (InterpState (), AppEventCompletions) -> IO ()
callback = Text
-> AppState AppName
-> Either DaemonError (InterpState (), AppEventCompletions)
-> IO ()
forall n.
Text
-> AppState n
-> Either DaemonError (InterpState (), AppEventCompletions)
-> IO ()
replExecCb Text
cmd AppState AppName
finishedState
            -- While the command is running, put write some temporary confirmation that the command
            -- was run to the logs.
            AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put
                (AppState AppName -> EventM AppName (AppState AppName) ())
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> EventM AppName (AppState AppName) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppEventCompletions -> Text -> AppState AppName -> AppState AppName
forall n. AppEventCompletions -> Text -> AppState n -> AppState n
appendToLogs AppEventCompletions
forall a. Monoid a => a
mempty Text
cmd
                (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> AppState AppName -> AppState AppName
forall n. Text -> AppState n -> AppState n
replaceCommandBuffer Text
""
                (AppState AppName -> EventM AppName (AppState AppName) ())
-> AppState AppName -> EventM AppName (AppState AppName) ()
forall a b. (a -> b) -> a -> b
$ AppState AppName
appState{waitingOnRepl = True}
            EventM AppName (AppState AppName) ()
forall n s. Ord n => EventM n s ()
B.invalidateCache
            -- Actually schedule the command.
            let interpState :: InterpState ()
interpState = AppState AppName -> InterpState ()
forall n. AppState n -> InterpState ()
AppState.interpState AppState AppName
appState
            IO () -> EventM AppName (AppState AppName) ()
forall a. IO a -> EventM AppName (AppState AppName) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> EventM AppName (AppState AppName) ())
-> IO () -> EventM AppName (AppState AppName) ()
forall a b. (a -> b) -> a -> b
$
                InterpState ()
-> DaemonIO (InterpState (), AppEventCompletions)
-> (Either DaemonError (InterpState (), AppEventCompletions)
    -> IO ())
-> IO ()
forall a r.
InterpState a
-> DaemonIO r -> (Either DaemonError r -> IO ()) -> IO ()
Daemon.scheduleWithCb InterpState ()
interpState (Text
-> InterpState () -> DaemonIO (InterpState (), AppEventCompletions)
forall a.
Monoid a =>
Text
-> InterpState a
-> ExceptT DaemonError IO (InterpState a, AppEventCompletions)
Daemon.execCleaned Text
cmd InterpState ()
interpState) Either DaemonError (InterpState (), AppEventCompletions) -> IO ()
callback
        B.VtyEvent (V.EvKey (V.KChar Char
'\t') []) -> do
            -- We want to preserve spaces, but not trailing newlines.
            let cmd :: Text
cmd = (Char -> Bool) -> Text -> Text
T.dropWhileEnd (Char
'\n' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==) (Text -> Text)
-> (AppState AppName -> Text) -> AppState AppName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppEventCompletions -> Text
T.unlines (AppEventCompletions -> Text)
-> (AppState AppName -> AppEventCompletions)
-> AppState AppName
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState AppName -> AppEventCompletions
forall {n}. AppState n -> AppEventCompletions
editorContents (AppState AppName -> Text) -> AppState AppName -> Text
forall a b. (a -> b) -> a -> b
$ AppState AppName
appState
            let callback :: Either DaemonError (InterpState (), (Text, AppEventCompletions))
-> IO ()
callback = Text
-> AppState AppName
-> Either DaemonError (InterpState (), (Text, AppEventCompletions))
-> IO ()
forall n.
Text
-> AppState n
-> Either DaemonError (InterpState (), (Text, AppEventCompletions))
-> IO ()
tabCompleteCb Text
cmd AppState AppName
appState
            let interpState :: InterpState ()
interpState = AppState AppName -> InterpState ()
forall n. AppState n -> InterpState ()
AppState.interpState AppState AppName
appState
            AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put AppState AppName
appState
            -- Schedule the tab completion.
            IO () -> EventM AppName (AppState AppName) ()
forall a. IO a -> EventM AppName (AppState AppName) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> EventM AppName (AppState AppName) ())
-> IO () -> EventM AppName (AppState AppName) ()
forall a b. (a -> b) -> a -> b
$
                InterpState ()
-> DaemonIO (InterpState (), (Text, AppEventCompletions))
-> (Either
      DaemonError (InterpState (), (Text, AppEventCompletions))
    -> IO ())
-> IO ()
forall a r.
InterpState a
-> DaemonIO r -> (Either DaemonError r -> IO ()) -> IO ()
Daemon.scheduleWithCb InterpState ()
interpState (Text
-> InterpState ()
-> DaemonIO (InterpState (), (Text, AppEventCompletions))
forall a.
Monoid a =>
Text
-> InterpState a
-> DaemonIO (InterpState a, (Text, AppEventCompletions))
Daemon.tabComplete Text
cmd InterpState ()
interpState) Either DaemonError (InterpState (), (Text, AppEventCompletions))
-> IO ()
callback
        B.VtyEvent (V.EvKey (V.KChar Char
'x') [Modifier
V.MCtrl]) ->
            -- Toggle out of the interpreter.
            EventM AppName (AppState AppName) ()
leaveInterpreter
        B.VtyEvent (V.EvKey Key
V.KEsc [Modifier]
_) -> do
            if Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ AppState AppName
appState AppState AppName -> Getting Bool (AppState AppName) Bool -> Bool
forall s a. s -> Getting a s a -> a
^. (AppInterpState Text AppName
 -> Const Bool (AppInterpState Text AppName))
-> AppState AppName -> Const Bool (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Const Bool (AppInterpState Text AppName))
 -> AppState AppName -> Const Bool (AppState AppName))
-> ((Bool -> Const Bool Bool)
    -> AppInterpState Text AppName
    -> Const Bool (AppInterpState Text AppName))
-> Getting Bool (AppState AppName) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool)
-> AppInterpState Text AppName
-> Const Bool (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock
                then -- Exit scroll mode first.
                    AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (ASetter (AppState AppName) (AppState AppName) Bool Bool
-> Bool -> AppState AppName -> AppState AppName
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ((AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> ((Bool -> Identity Bool)
    -> AppInterpState Text AppName
    -> Identity (AppInterpState Text AppName))
-> ASetter (AppState AppName) (AppState AppName) Bool Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> AppInterpState Text AppName
-> Identity (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) Bool
True AppState AppName
appState)
                else -- Also toggle out of the interpreter.
                    EventM AppName (AppState AppName) ()
leaveInterpreter

        -- Selecting previous commands.
        B.VtyEvent (V.EvKey Key
V.KUp [Modifier]
_) -> do
            let maybeStoreBuffer :: AppState n -> AppState n
maybeStoreBuffer AppState n
s =
                    if Bool -> Bool
not (AppInterpState Text n -> Bool
forall s n. AppInterpState s n -> Bool
AIS.isScanningHist (AppState n -> AppInterpState Text n
forall {n}. AppState n -> AppInterpState Text n
getAis AppState n
s))
                        then AppState n -> AppState n
forall {n}. AppState n -> AppState n
storeCommandBuffer AppState n
s
                        else AppState n
s
            let wDebug :: AppState n -> AppState n
wDebug AppState n
s =
                    Text -> AppState n -> AppState n
forall n. Text -> AppState n -> AppState n
writeDebugLog
                        ( Text
"handled Up; historyPos is "
                            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Int -> Text
forall a. Show a => a -> Text
showT (Int -> Text) -> (AppState n -> Int) -> AppState n -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppInterpState Text n -> Int
forall s n. AppInterpState s n -> Int
AIS.historyPos (AppInterpState Text n -> Int)
-> (AppState n -> AppInterpState Text n) -> AppState n -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState n -> AppInterpState Text n
forall {n}. AppState n -> AppInterpState Text n
getAis (AppState n -> Text) -> AppState n -> Text
forall a b. (a -> b) -> a -> b
$ AppState n
s)
                        )
                        AppState n
s
            let appState' :: AppState AppName
appState' =
                    AppState AppName -> AppState AppName
forall {n}. AppState n -> AppState n
wDebug
                        (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState AppName -> AppState AppName
forall {n}. AppState n -> AppState n
replaceCommandBufferWithHist -- Display the history.
                        (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> (AppInterpState Text AppName -> AppInterpState Text AppName)
-> AppState AppName
-> AppState AppName
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
Lens.over (AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState AppInterpState Text AppName -> AppInterpState Text AppName
forall s n. AppInterpState s n -> AppInterpState s n
AIS.pastHistoryPos -- Go back in time.
                        (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState AppName -> AppState AppName
forall {n}. AppState n -> AppState n
maybeStoreBuffer -- Store the buffer if we're not scanning already.
                        (AppState AppName -> AppState AppName)
-> AppState AppName -> AppState AppName
forall a b. (a -> b) -> a -> b
$ AppState AppName
appState
            AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put AppState AppName
appState'
        B.VtyEvent (V.EvKey Key
V.KDown [Modifier]
_) -> do
            let wDebug :: AppState n -> AppState n
wDebug AppState n
s =
                    Text -> AppState n -> AppState n
forall n. Text -> AppState n -> AppState n
writeDebugLog
                        ( Text
"handled Down; historyPos is "
                            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Int -> Text
forall a. Show a => a -> Text
showT (Int -> Text) -> (AppState n -> Int) -> AppState n -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppInterpState Text n -> Int
forall s n. AppInterpState s n -> Int
AIS.historyPos (AppInterpState Text n -> Int)
-> (AppState n -> AppInterpState Text n) -> AppState n -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState n -> AppInterpState Text n
forall {n}. AppState n -> AppInterpState Text n
getAis (AppState n -> Text) -> AppState n -> Text
forall a b. (a -> b) -> a -> b
$ AppState n
s)
                        )
                        AppState n
s
            let appState' :: AppState AppName
appState' =
                    AppState AppName -> AppState AppName
forall {n}. AppState n -> AppState n
wDebug
                        (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState AppName -> AppState AppName
forall {n}. AppState n -> AppState n
replaceCommandBufferWithHist -- Display the history.
                        (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> (AppInterpState Text AppName -> AppInterpState Text AppName)
-> AppState AppName
-> AppState AppName
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
Lens.over (AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState AppInterpState Text AppName -> AppInterpState Text AppName
forall s n. AppInterpState s n -> AppInterpState s n
AIS.futHistoryPos -- Go forward in time.
                        (AppState AppName -> AppState AppName)
-> AppState AppName -> AppState AppName
forall a b. (a -> b) -> a -> b
$ AppState AppName
appState
            AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put AppState AppName
appState'

        -- Scrolling back through the logs.
        B.VtyEvent (V.EvKey Key
V.KPageDown [Modifier]
_) ->
            ViewportScroll AppName
-> forall s. Direction -> EventM AppName s ()
forall n. ViewportScroll n -> forall s. Direction -> EventM n s ()
B.vScrollPage (AppName -> ViewportScroll AppName
forall n. n -> ViewportScroll n
B.viewportScroll AppName
LiveInterpreterViewport) Direction
B.Down
        B.VtyEvent (V.EvKey Key
V.KPageUp [Modifier]
_) -> do
            ViewportScroll AppName
-> forall s. Direction -> EventM AppName s ()
forall n. ViewportScroll n -> forall s. Direction -> EventM n s ()
B.vScrollPage (AppName -> ViewportScroll AppName
forall n. n -> ViewportScroll n
B.viewportScroll AppName
LiveInterpreterViewport) Direction
B.Up
            AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (ASetter (AppState AppName) (AppState AppName) Bool Bool
-> Bool -> AppState AppName -> AppState AppName
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ((AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> ((Bool -> Identity Bool)
    -> AppInterpState Text AppName
    -> Identity (AppInterpState Text AppName))
-> ASetter (AppState AppName) (AppState AppName) Bool Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> AppInterpState Text AppName
-> Identity (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) Bool
False AppState AppName
appState)
        B.VtyEvent (V.EvKey (V.KChar Char
'n') [Modifier
V.MCtrl]) -> do
            -- Invert the viewLock.
            AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (ASetter (AppState AppName) (AppState AppName) Bool Bool
-> (Bool -> Bool) -> AppState AppName -> AppState AppName
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
Lens.over ((AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> ((Bool -> Identity Bool)
    -> AppInterpState Text AppName
    -> Identity (AppInterpState Text AppName))
-> ASetter (AppState AppName) (AppState AppName) Bool Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> AppInterpState Text AppName
-> Identity (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) Bool -> Bool
not AppState AppName
appState)

        -- While scrolling (viewLock disabled), allow resizing the live interpreter history.
        B.VtyEvent (V.EvKey (V.KChar Char
'+') [])
            | Bool -> Bool
not (AppState AppName
appState AppState AppName -> Getting Bool (AppState AppName) Bool -> Bool
forall s a. s -> Getting a s a -> a
^. (AppInterpState Text AppName
 -> Const Bool (AppInterpState Text AppName))
-> AppState AppName -> Const Bool (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Const Bool (AppInterpState Text AppName))
 -> AppState AppName -> Const Bool (AppState AppName))
-> ((Bool -> Const Bool Bool)
    -> AppInterpState Text AppName
    -> Const Bool (AppInterpState Text AppName))
-> Getting Bool (AppState AppName) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool)
-> AppInterpState Text AppName
-> Const Bool (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) -> do
                AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (Int -> AppState AppName -> AppState AppName
forall n. Int -> AppState n -> AppState n
AppState.changeReplWidgetSize Int
1 AppState AppName
appState)
        B.VtyEvent (V.EvKey (V.KChar Char
'-') [])
            | Bool -> Bool
not (AppState AppName
appState AppState AppName -> Getting Bool (AppState AppName) Bool -> Bool
forall s a. s -> Getting a s a -> a
^. (AppInterpState Text AppName
 -> Const Bool (AppInterpState Text AppName))
-> AppState AppName -> Const Bool (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Const Bool (AppInterpState Text AppName))
 -> AppState AppName -> Const Bool (AppState AppName))
-> ((Bool -> Const Bool Bool)
    -> AppInterpState Text AppName
    -> Const Bool (AppInterpState Text AppName))
-> Getting Bool (AppState AppName) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool)
-> AppInterpState Text AppName
-> Const Bool (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) -> do
                AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (Int -> AppState AppName -> AppState AppName
forall n. Int -> AppState n -> AppState n
AppState.changeReplWidgetSize (-Int
1) AppState AppName
appState)

        -- Actually handle keystrokes.
        BrickEvent AppName e
ev' ->
            if AppState AppName -> Bool
forall n. AppState n -> Bool
waitingOnRepl AppState AppName
appState
                then
                    -- Don't print a prompt if we're waiting.
                    () -> EventM AppName (AppState AppName) ()
forall a. a -> EventM AppName (AppState AppName) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                else do
                    -- When typing, bring us back down to the terminal.
                    AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (ASetter (AppState AppName) (AppState AppName) Bool Bool
-> Bool -> AppState AppName -> AppState AppName
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ((AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> ((Bool -> Identity Bool)
    -> AppInterpState Text AppName
    -> Identity (AppInterpState Text AppName))
-> ASetter (AppState AppName) (AppState AppName) Bool Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> AppInterpState Text AppName
-> Identity (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) Bool
True AppState AppName
appState)
                    -- Actually handle text input commands.
                    LensLike'
  (Zoomed (EventM AppName (Editor Text AppName)) ())
  (AppState AppName)
  (Editor Text AppName)
-> EventM AppName (Editor Text AppName) ()
-> EventM AppName (AppState AppName) ()
forall c.
LensLike'
  (Zoomed (EventM AppName (Editor Text AppName)) c)
  (AppState AppName)
  (Editor Text AppName)
-> EventM AppName (Editor Text AppName) c
-> EventM AppName (AppState AppName) c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
B.zoom (Editor Text AppName
 -> Focusing
      (StateT (EventState AppName) IO) () (Editor Text AppName))
-> AppState AppName
-> Focusing (StateT (EventState AppName) IO) () (AppState AppName)
LensLike'
  (Zoomed (EventM AppName (Editor Text AppName)) ())
  (AppState AppName)
  (Editor Text AppName)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> AppState n -> f (AppState n)
liveEditor (EventM AppName (Editor Text AppName) ()
 -> EventM AppName (AppState AppName) ())
-> EventM AppName (Editor Text AppName) ()
-> EventM AppName (AppState AppName) ()
forall a b. (a -> b) -> a -> b
$ BrickEvent AppName e -> EventM AppName (Editor Text AppName) ()
forall n t e.
(Eq n, DecodeUtf8 t, Eq t, GenericTextZipper t) =>
BrickEvent n e -> EventM n (Editor t n) ()
BE.handleEditorEvent BrickEvent AppName e
ev'
  where
    editorContents :: AppState n -> AppEventCompletions
editorContents AppState n
appState = Editor Text n -> AppEventCompletions
forall t n. Monoid t => Editor t n -> [t]
BE.getEditContents (Editor Text n -> AppEventCompletions)
-> Editor Text n -> AppEventCompletions
forall a b. (a -> b) -> a -> b
$ AppState n
appState AppState n
-> Getting (Editor Text n) (AppState n) (Editor Text n)
-> Editor Text n
forall s a. s -> Getting a s a -> a
^. Getting (Editor Text n) (AppState n) (Editor Text n)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> AppState n -> f (AppState n)
liveEditor
    storeCommandBuffer :: AppState n -> AppState n
storeCommandBuffer AppState n
appState =
        ASetter
  (AppState n) (AppState n) AppEventCompletions AppEventCompletions
-> AppEventCompletions -> AppState n -> AppState n
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ((AppInterpState Text n -> Identity (AppInterpState Text n))
-> AppState n -> Identity (AppState n)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text n -> Identity (AppInterpState Text n))
 -> AppState n -> Identity (AppState n))
-> ((AppEventCompletions -> Identity AppEventCompletions)
    -> AppInterpState Text n -> Identity (AppInterpState Text n))
-> ASetter
     (AppState n) (AppState n) AppEventCompletions AppEventCompletions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AppEventCompletions -> Identity AppEventCompletions)
-> AppInterpState Text n -> Identity (AppInterpState Text n)
forall s n (f :: * -> *).
Functor f =>
([s] -> f [s]) -> AppInterpState s n -> f (AppInterpState s n)
AIS.commandBuffer) (AppState n -> AppEventCompletions
forall {n}. AppState n -> AppEventCompletions
editorContents AppState n
appState) AppState n
appState
    getAis :: AppState n -> AppInterpState Text n
getAis AppState n
s = AppState n
s AppState n
-> Getting
     (AppInterpState Text n) (AppState n) (AppInterpState Text n)
-> AppInterpState Text n
forall s a. s -> Getting a s a -> a
^. Getting
  (AppInterpState Text n) (AppState n) (AppInterpState Text n)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState
    getCommandAtHist :: Int -> AppState n -> [T.Text]
    getCommandAtHist :: forall n. Int -> AppState n -> AppEventCompletions
getCommandAtHist Int
i AppState n
s
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = AppState n
s AppState n
-> Getting AppEventCompletions (AppState n) AppEventCompletions
-> AppEventCompletions
forall s a. s -> Getting a s a -> a
^. (AppInterpState Text n
 -> Const AppEventCompletions (AppInterpState Text n))
-> AppState n -> Const AppEventCompletions (AppState n)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text n
  -> Const AppEventCompletions (AppInterpState Text n))
 -> AppState n -> Const AppEventCompletions (AppState n))
-> ((AppEventCompletions
     -> Const AppEventCompletions AppEventCompletions)
    -> AppInterpState Text n
    -> Const AppEventCompletions (AppInterpState Text n))
-> Getting AppEventCompletions (AppState n) AppEventCompletions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AppEventCompletions
 -> Const AppEventCompletions AppEventCompletions)
-> AppInterpState Text n
-> Const AppEventCompletions (AppInterpState Text n)
forall s n (f :: * -> *).
Functor f =>
([s] -> f [s]) -> AppInterpState s n -> f (AppInterpState s n)
AIS.commandBuffer
        | Bool
otherwise = AppEventCompletions
-> [AppEventCompletions] -> Int -> AppEventCompletions
forall a. a -> [a] -> Int -> a
atDef (AppEventCompletions -> [AppEventCompletions] -> AppEventCompletions
forall a. a -> [a] -> a
lastDef [] [AppEventCompletions]
hist) [AppEventCompletions]
hist (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
      where
        hist :: [AppEventCompletions]
hist = AppState n
s AppState n
-> Getting [AppEventCompletions] (AppState n) [AppEventCompletions]
-> [AppEventCompletions]
forall s a. s -> Getting a s a -> a
^. (AppInterpState Text n
 -> Const [AppEventCompletions] (AppInterpState Text n))
-> AppState n -> Const [AppEventCompletions] (AppState n)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text n
  -> Const [AppEventCompletions] (AppInterpState Text n))
 -> AppState n -> Const [AppEventCompletions] (AppState n))
-> (([AppEventCompletions]
     -> Const [AppEventCompletions] [AppEventCompletions])
    -> AppInterpState Text n
    -> Const [AppEventCompletions] (AppInterpState Text n))
-> Getting [AppEventCompletions] (AppState n) [AppEventCompletions]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AppInterpState Text n -> [AppEventCompletions])
-> SimpleGetter (AppInterpState Text n) [AppEventCompletions]
forall s a. (s -> a) -> SimpleGetter s a
Lens.to AppInterpState Text n -> [AppEventCompletions]
forall s n. AppInterpState s n -> [[s]]
AIS.cmdHistory

    leaveInterpreter :: EventM AppName (AppState AppName) ()
leaveInterpreter = AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (AppState AppName -> EventM AppName (AppState AppName) ())
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> EventM AppName (AppState AppName) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppState AppName -> AppState AppName
forall {n}. AppState n -> AppState n
toggleActiveLineInterpreter (AppState AppName -> EventM AppName (AppState AppName) ())
-> EventM AppName (AppState AppName) (AppState AppName)
-> EventM AppName (AppState AppName) ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< EventM AppName (AppState AppName) (AppState AppName)
forall s (m :: * -> *). MonadState s m => m s
B.get

    replaceCommandBufferWithHist :: AppState n -> AppState n
    replaceCommandBufferWithHist :: forall {n}. AppState n -> AppState n
replaceCommandBufferWithHist s :: AppState n
s@AppState{AppInterpState Text n
_appInterpState :: AppInterpState Text n
$sel:_appInterpState:AppState :: forall {n}. AppState n -> AppInterpState Text n
_appInterpState} = Text -> AppState n -> AppState n
forall n. Text -> AppState n -> AppState n
replaceCommandBuffer Text
cmd AppState n
s
      where
        cmd :: Text
cmd = AppEventCompletions -> Text
T.unlines (AppEventCompletions -> Text)
-> (AppState n -> AppEventCompletions) -> AppState n -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> AppState n -> AppEventCompletions
forall n. Int -> AppState n -> AppEventCompletions
getCommandAtHist (AppInterpState Text n -> Int
forall s n. AppInterpState s n -> Int
AIS.historyPos AppInterpState Text n
_appInterpState) (AppState n -> Text) -> AppState n -> Text
forall a b. (a -> b) -> a -> b
$ AppState n
s

appendToLogs
    :: [T.Text]
    -- ^ Logs between commands.
    -> T.Text
    -- ^ The command sent to produce the logs.
    -> AppState n
    -- ^ State to update.
    -> AppState n
    -- ^ Updated state.
appendToLogs :: forall n. AppEventCompletions -> Text -> AppState n -> AppState n
appendToLogs AppEventCompletions
logs Text
promptEntry AppState n
state = AppState n
state{interpLogs = take interpreterLogLimit combinedLogs}
  where
    combinedLogs :: AppEventCompletions
combinedLogs = AppEventCompletions -> AppEventCompletions
forall a. [a] -> [a]
reverse AppEventCompletions
logs AppEventCompletions -> AppEventCompletions -> AppEventCompletions
forall a. Semigroup a => a -> a -> a
<> (Text
formattedWithPrompt Text -> AppEventCompletions -> AppEventCompletions
forall a. a -> [a] -> [a]
: AppState n -> AppEventCompletions
forall {n}. AppState n -> AppEventCompletions
interpLogs AppState n
state)
    formattedWithPrompt :: Text
formattedWithPrompt = AppConfig -> Text
getInterpreterPrompt (AppState n -> AppConfig
forall n. AppState n -> AppConfig
appConfig AppState n
state) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
promptEntry
    -- TODO: Should be configurable?
    interpreterLogLimit :: Int
interpreterLogLimit = Int
1000

-- | Replace the command buffer with the given strings of Text.
replaceCommandBuffer
    :: T.Text
    -- ^ Text to replace with.
    -> AppState n
    -- ^ State to modify.
    -> AppState n
    -- ^ New state.
replaceCommandBuffer :: forall n. Text -> AppState n -> AppState n
replaceCommandBuffer Text
replacement AppState n
s = ASetter (AppState n) (AppState n) (Editor Text n) (Editor Text n)
-> Editor Text n -> AppState n -> AppState n
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ASetter (AppState n) (AppState n) (Editor Text n) (Editor Text n)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> AppState n -> f (AppState n)
liveEditor Editor Text n
newEditor AppState n
s
  where
    zipp :: T.TextZipper T.Text -> T.TextZipper T.Text
    zipp :: TextZipper Text -> TextZipper Text
zipp = TextZipper Text -> TextZipper Text
forall a. Monoid a => TextZipper a -> TextZipper a
T.killToEOF (TextZipper Text -> TextZipper Text)
-> (TextZipper Text -> TextZipper Text)
-> TextZipper Text
-> TextZipper Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> TextZipper Text -> TextZipper Text
forall a. Monoid a => a -> TextZipper a -> TextZipper a
T.insertMany Text
replacement (TextZipper Text -> TextZipper Text)
-> (TextZipper Text -> TextZipper Text)
-> TextZipper Text
-> TextZipper Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextZipper Text -> TextZipper Text
forall a. Monoid a => TextZipper a -> TextZipper a
T.gotoBOF
    newEditor :: Editor Text n
newEditor = (TextZipper Text -> TextZipper Text)
-> Editor Text n -> Editor Text n
forall t n.
(TextZipper t -> TextZipper t) -> Editor t n -> Editor t n
BE.applyEdit TextZipper Text -> TextZipper Text
zipp (AppState n
s AppState n
-> Getting (Editor Text n) (AppState n) (Editor Text n)
-> Editor Text n
forall s a. s -> Getting a s a -> a
^. Getting (Editor Text n) (AppState n) (Editor Text n)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> AppState n -> f (AppState n)
liveEditor)

-- -------------------------------------------------------------------------------------------------
-- Callbacks and Callback utils
-- -------------------------------------------------------------------------------------------------

-- | Live Interpreter/REPL Callback. Called asynchronously after the 'DaemonIO' resolves.
replExecCb
    :: T.Text
    -- ^ Command sent and ran on the Daemon.
    -> AppState n
    -- ^ 'AppState' to use for asynchronous channel communication.
    -> Either Daemon.DaemonError (Daemon.InterpState (), [T.Text])
    -- ^ The incoming response from the Daemon for the 'step' (or similar) operation.
    -> IO ()
    -- ^ IO used to write to the event bounded channel.
replExecCb :: forall n.
Text
-> AppState n
-> Either DaemonError (InterpState (), AppEventCompletions)
-> IO ()
replExecCb Text
cmd AppState n
appState (Right (InterpState ()
interpState, AppEventCompletions
logs)) =
    BChan (CustomAppEvent (AppState n))
-> CustomAppEvent (AppState n) -> IO ()
forall a. BChan a -> a -> IO ()
B.writeBChan (AppState n -> BChan (CustomAppEvent (AppState n))
forall n. AppState n -> BChan (CustomAppEvent (AppState n))
AppState.eventChannel AppState n
appState) (AppState n
-> Text -> AppEventCompletions -> CustomAppEvent (AppState n)
forall state.
state -> Text -> AppEventCompletions -> CustomAppEvent state
ReplExecCb AppState n
appState{interpState} Text
cmd AppEventCompletions
logs)
replExecCb Text
_ AppState n
appState (Left DaemonError
msg) =
    BChan (CustomAppEvent (AppState n))
-> CustomAppEvent (AppState n) -> IO ()
forall a. BChan a -> a -> IO ()
B.writeBChan (AppState n -> BChan (CustomAppEvent (AppState n))
forall n. AppState n -> BChan (CustomAppEvent (AppState n))
AppState.eventChannel AppState n
appState) (AppState n -> Text -> CustomAppEvent (AppState n)
forall state. state -> Text -> CustomAppEvent state
ErrorOnCb AppState n
appState (DaemonError -> Text
forall a. Show a => a -> Text
showT DaemonError
msg))

tabCompleteCb
    :: T.Text
    -- ^ Partial command to get completion of.
    -> AppState n
    -> Either Daemon.DaemonError (Daemon.InterpState (), (T.Text, [T.Text]))
    -> IO ()
tabCompleteCb :: forall n.
Text
-> AppState n
-> Either DaemonError (InterpState (), (Text, AppEventCompletions))
-> IO ()
tabCompleteCb Text
cmd AppState n
appState (Right (InterpState ()
interpState, (Text
prefix, AppEventCompletions
completions))) =
    BChan (CustomAppEvent (AppState n))
-> CustomAppEvent (AppState n) -> IO ()
forall a. BChan a -> a -> IO ()
B.writeBChan
        (AppState n -> BChan (CustomAppEvent (AppState n))
forall n. AppState n -> BChan (CustomAppEvent (AppState n))
AppState.eventChannel AppState n
appState)
        (AppState n
-> Text
-> (Text, AppEventCompletions)
-> CustomAppEvent (AppState n)
forall state.
state
-> Text -> (Text, AppEventCompletions) -> CustomAppEvent state
ReplTabCompleteCb AppState n
appState{interpState} Text
cmd (Text
prefix, AppEventCompletions
completions))
tabCompleteCb Text
_ AppState n
appState (Left DaemonError
msg) =
    BChan (CustomAppEvent (AppState n))
-> CustomAppEvent (AppState n) -> IO ()
forall a. BChan a -> a -> IO ()
B.writeBChan (AppState n -> BChan (CustomAppEvent (AppState n))
forall n. AppState n -> BChan (CustomAppEvent (AppState n))
AppState.eventChannel AppState n
appState) (AppState n -> Text -> CustomAppEvent (AppState n)
forall state. state -> Text -> CustomAppEvent state
ErrorOnCb AppState n
appState (DaemonError -> Text
forall a. Show a => a -> Text
showT DaemonError
msg))

-- | Synchronous code to update the state after a InterpreterEvent callback.
handleInterpWindowPostCb
    :: CustomAppEvent (AppState AppName) -> B.EventM AppName (AppState AppName) ()
handleInterpWindowPostCb :: CustomAppEvent (AppState AppName)
-> EventM AppName (AppState AppName) ()
handleInterpWindowPostCb (ReplExecCb AppState AppName
appState Text
cmd AppEventCompletions
newLogs) = do
    let newEditor :: Editor Text AppName
newEditor =
            (TextZipper Text -> TextZipper Text)
-> Editor Text AppName -> Editor Text AppName
forall t n.
(TextZipper t -> TextZipper t) -> Editor t n -> Editor t n
BE.applyEdit
                (TextZipper Text -> TextZipper Text
forall a. Monoid a => TextZipper a -> TextZipper a
T.killToEOF (TextZipper Text -> TextZipper Text)
-> (TextZipper Text -> TextZipper Text)
-> TextZipper Text
-> TextZipper Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextZipper Text -> TextZipper Text
forall a. Monoid a => TextZipper a -> TextZipper a
T.gotoBOF)
                (AppState AppName
appState AppState AppName
-> Getting
     (Editor Text AppName) (AppState AppName) (Editor Text AppName)
-> Editor Text AppName
forall s a. s -> Getting a s a -> a
^. Getting
  (Editor Text AppName) (AppState AppName) (Editor Text AppName)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> AppState n -> f (AppState n)
liveEditor)
    let newAppState2 :: AppState AppName
newAppState2 =
            Text -> AppState AppName -> AppState AppName
forall n. Text -> AppState n -> AppState n
writeDebugLog (Text
"handled Enter: Ran '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cmd Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'")
                (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ASetter (AppState AppName) (AppState AppName) Bool Bool
-> Bool -> AppState AppName -> AppState AppName
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ((AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> ((Bool -> Identity Bool)
    -> AppInterpState Text AppName
    -> Identity (AppInterpState Text AppName))
-> ASetter (AppState AppName) (AppState AppName) Bool Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> AppInterpState Text AppName
-> Identity (AppInterpState Text AppName)
forall s n (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> AppInterpState s n -> f (AppInterpState s n)
AIS.viewLock) Bool
True
                (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((AppInterpState Text AppName
  -> Identity (AppInterpState Text AppName))
 -> AppState AppName -> Identity (AppState AppName))
-> (AppInterpState Text AppName -> AppInterpState Text AppName)
-> AppState AppName
-> AppState AppName
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
Lens.over (AppInterpState Text AppName
 -> Identity (AppInterpState Text AppName))
-> AppState AppName -> Identity (AppState AppName)
forall n (f :: * -> *).
Functor f =>
(AppInterpState Text n -> f (AppInterpState Text n))
-> AppState n -> f (AppState n)
appInterpState (AppEventCompletions
-> AppInterpState Text AppName -> AppInterpState Text AppName
forall s n. [s] -> AppInterpState s n -> AppInterpState s n
AIS.pushHistory [Text
cmd])
                (AppState AppName -> AppState AppName)
-> AppState AppName -> AppState AppName
forall a b. (a -> b) -> a -> b
$ AppEventCompletions -> Text -> AppState AppName -> AppState AppName
forall n. AppEventCompletions -> Text -> AppState n -> AppState n
appendToLogs AppEventCompletions
newLogs Text
cmd AppState AppName
appState
    let appStateFinalIO :: IO (AppState AppName)
appStateFinalIO = AppState AppName -> IO (AppState AppName)
forall n. AppState n -> IO (AppState n)
updateSourceMap (ASetter
  (AppState AppName)
  (AppState AppName)
  (Editor Text AppName)
  (Editor Text AppName)
-> Editor Text AppName -> AppState AppName -> AppState AppName
forall s t a b. ASetter s t a b -> b -> s -> t
Lens.set ASetter
  (AppState AppName)
  (AppState AppName)
  (Editor Text AppName)
  (Editor Text AppName)
forall n (f :: * -> *).
Functor f =>
(Editor Text n -> f (Editor Text n))
-> AppState n -> f (AppState n)
liveEditor Editor Text AppName
newEditor AppState AppName
newAppState2)
    AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put (AppState AppName -> EventM AppName (AppState AppName) ())
-> EventM AppName (AppState AppName) (AppState AppName)
-> EventM AppName (AppState AppName) ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (AppState AppName)
-> EventM AppName (AppState AppName) (AppState AppName)
forall a. IO a -> EventM AppName (AppState AppName) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (AppState AppName)
appStateFinalIO
    -- Invalidate the entire render state of the application
    -- because we don't know what's actually changed here now.
    EventM AppName (AppState AppName) ()
forall n s. Ord n => EventM n s ()
B.invalidateCache
handleInterpWindowPostCb (ReplTabCompleteCb AppState AppName
appState Text
cmd (Text
prefix, AppEventCompletions
completions)) = do
    let maxCompletionLen :: Int
maxCompletionLen = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length (Text -> Int) -> AppEventCompletions -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AppEventCompletions
completions
    let columnPadding :: Int
columnPadding = Int
1
    Extent AppName
extent <-
        AppName
-> EventM AppName (AppState AppName) (Maybe (Extent AppName))
forall n s. Eq n => n -> EventM n s (Maybe (Extent n))
B.lookupExtent AppName
LiveInterpreterViewport EventM AppName (AppState AppName) (Maybe (Extent AppName))
-> (Maybe (Extent AppName)
    -> EventM AppName (AppState AppName) (Extent AppName))
-> EventM AppName (AppState AppName) (Extent AppName)
forall a b.
EventM AppName (AppState AppName) a
-> (a -> EventM AppName (AppState AppName) b)
-> EventM AppName (AppState AppName) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            Just Extent AppName
e -> Extent AppName
-> EventM AppName (AppState AppName) (Extent AppName)
forall a. a -> EventM AppName (AppState AppName) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Extent AppName
e
            Maybe (Extent AppName)
Nothing -> [Char] -> EventM AppName (AppState AppName) (Extent AppName)
forall a. HasCallStack => [Char] -> a
error [Char]
"Could not find extent of LiveInterpreterViewport"
    let interpWidth :: Int
interpWidth = (Int, Int) -> Int
forall a b. (a, b) -> a
fst ((Int, Int) -> Int)
-> (Extent AppName -> (Int, Int)) -> Extent AppName -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Extent AppName -> (Int, Int)
forall n. Extent n -> (Int, Int)
B.extentSize (Extent AppName -> Int) -> Extent AppName -> Int
forall a b. (a -> b) -> a -> b
$ Extent AppName
extent
    let completionColWidth :: Int
completionColWidth = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Int
interpWidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) Int
maxCompletionLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
columnPadding
    let numCols :: Int
numCols = Int
interpWidth Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
completionColWidth
    let updateCompletions :: AppEventCompletions -> AppState AppName -> AppState AppName
updateCompletions AppEventCompletions
cs AppState AppName
s = case AppEventCompletions
cs of
            -- Only one completion, just replace the entire buffer with it.
            [Text
c] -> Text -> AppState AppName -> AppState AppName
forall n. Text -> AppState n -> AppState n
replaceCommandBuffer (Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
c Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ") AppState AppName
s
            -- No completions. Just go to a new prompt.
            [] -> AppEventCompletions -> Text -> AppState AppName -> AppState AppName
forall n. AppEventCompletions -> Text -> AppState n -> AppState n
appendToLogs [] Text
cmd AppState AppName
s
            -- Replace the buffer with the longest possible prefix among options, and
            -- print the remaining.
            AppEventCompletions
_ ->
                Text -> AppState AppName -> AppState AppName
forall n. Text -> AppState n -> AppState n
replaceCommandBuffer (Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> AppEventCompletions -> Text
commonPrefixes AppEventCompletions
cs)
                    (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppEventCompletions -> Text -> AppState AppName -> AppState AppName
forall n. AppEventCompletions -> Text -> AppState n -> AppState n
appendToLogs (Int -> Int -> AppEventCompletions -> AppEventCompletions
reflowText Int
numCols Int
completionColWidth AppEventCompletions
cs) Text
cmd
                    (AppState AppName -> AppState AppName)
-> AppState AppName -> AppState AppName
forall a b. (a -> b) -> a -> b
$ AppState AppName
s
    AppState AppName -> EventM AppName (AppState AppName) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
B.put
        (AppState AppName -> EventM AppName (AppState AppName) ())
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> EventM AppName (AppState AppName) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> AppState AppName -> AppState AppName
forall n. Text -> AppState n -> AppState n
writeDebugLog
            ( Text
"handled Tab, Prefix was: '"
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cmd
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"' completions were: "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> AppEventCompletions -> Text
forall a. Show a => a -> Text
showT AppEventCompletions
completions
            )
        (AppState AppName -> AppState AppName)
-> (AppState AppName -> AppState AppName)
-> AppState AppName
-> AppState AppName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppEventCompletions -> AppState AppName -> AppState AppName
updateCompletions AppEventCompletions
completions
        (AppState AppName -> EventM AppName (AppState AppName) ())
-> AppState AppName -> EventM AppName (AppState AppName) ()
forall a b. (a -> b) -> a -> b
$ AppState AppName
appState
-- For all other AppEvent types, ignore them. They're handled elsewhere.
handleInterpWindowPostCb CustomAppEvent (AppState AppName)
_ = () -> EventM AppName (AppState AppName) ()
forall a. a -> EventM AppName (AppState AppName) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()