From dcb25bbbb8e9c12f9632feedb9ab17776d0ecec2 Mon Sep 17 00:00:00 2001 From: Benjamin Summers Date: Wed, 18 Sep 2019 15:07:53 -0700 Subject: [PATCH] Track terminal state in pure code. --- pkg/king/lib/Vere/Term/Logic.hs | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 pkg/king/lib/Vere/Term/Logic.hs diff --git a/pkg/king/lib/Vere/Term/Logic.hs b/pkg/king/lib/Vere/Term/Logic.hs new file mode 100644 index 000000000..89a0d00e1 --- /dev/null +++ b/pkg/king/lib/Vere/Term/Logic.hs @@ -0,0 +1,88 @@ +module Vere.Term.Logic + ( SpinnerCause(..), Ev(..), Ef(..) + , init + , step + , drawState + ) where + +import UrbitPrelude hiding (Empty, getCurrentTime, init) + +import Data.Sequence (Seq((:<|), Empty)) +import Urbit.Time (Wen) + + +-------------------------------------------------------------------------------- + +data SpinnerCause = User | Event Text + deriving (Show) + +type SpinnerState = Maybe SpinnerCause + +{- + %line -- Output a line above the edit line. + %spin -- Set the spinner state. + %bell -- Ring a bell (no change to the state). + %draw -- Redraw the current line (no change to the state). + %move -- Move the cursor position. + %edit -- Set the edit line, moving the cursor to the end. + %more -- Write the edit line to history, and clear it. +-} +data Ev + = EvLine Text + | EvSpin SpinnerState + | EvMove Word + | EvBell + | EvDraw + | EvEdit Text + | EvMore + deriving (Show) + +data Ef + = EfClear + | EfWrite Text + | EfShift Int + | EfRing + | EfSpin SpinnerState + deriving (Show) + +data St = St + { sHistory :: Seq Text + , sLine :: Text + , sCurPos :: Word + , sSpinner :: SpinnerState + } + deriving (Show) + +-------------------------------------------------------------------------------- + +init :: Wen -> St +init now = St mempty "" 0 Nothing + +step :: St -> Ev -> St +step st@St{..} = \case + EvLine t -> st & record t + EvSpin s -> st { sSpinner = s } + EvMove w -> st { sCurPos = min w (word $ length sLine) } + EvEdit t -> st { sLine = t, sCurPos = word (length t) } + EvMore -> st { sLine = "", sCurPos = 0 } & record sLine + EvBell -> st + EvDraw -> st + where + word :: Integral i => i -> Word + word = fromIntegral + + record :: Text -> St -> St + record t st@St{..} = st { sHistory = trim (sHistory |> t) } + + trim :: Seq a -> Seq a + trim Empty = Empty + trim s | length s < 20 = s + trim (_ :<| s) = s + +drawState :: St -> [Ev] +drawState St{..} = hist <> out <> cur <> spin + where + hist = EvLine <$> toList sHistory + out = if null sLine then [] else [EvEdit sLine] + cur = if 0 == sCurPos then [] else [EvMove $ fromIntegral $ sCurPos] + spin = maybe [] (singleton . EvSpin . Just) sSpinner