From 37d10a1912b845e0b1a50062d84f5c50e41c4ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sun, 2 Feb 2025 10:24:13 +0100 Subject: Terminal: printing lines below prompt --- main/Terminal.hs | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/Terminal.hs b/main/Terminal.hs index d117640..21bbf4b 100644 --- a/main/Terminal.hs +++ b/main/Terminal.hs @@ -9,6 +9,9 @@ module Terminal ( TerminalLine, printLine, + printBottomLines, + clearBottomLines, + CompletionFunc, Completion, simpleCompletion, completeWordWithPrev, @@ -32,6 +35,7 @@ data Terminal = Terminal , termPrompt :: TVar String , termShowPrompt :: TVar Bool , termInput :: TVar ( String, String ) + , termBottomLines :: TVar [ String ] } data TerminalLine = TerminalLine @@ -67,6 +71,7 @@ initTerminal = do termPrompt <- newTVarIO "" termShowPrompt <- newTVarIO False termInput <- newTVarIO ( "", "" ) + termBottomLines <- newTVarIO [] return Terminal {..} bracketSet :: IO a -> (a -> IO b) -> a -> IO c -> IO c @@ -225,11 +230,60 @@ printLine tlTerminal@Terminal {..} str = do readTVar termShowPrompt >>= \case True -> getCurrentPromptLine tlTerminal False -> return "" - putStr $ "\r\ESC[K" <> str <> "\n" <> promptLine + putStr $ "\r\ESC[K" <> str <> "\n\ESC[K" <> promptLine + drawBottomLines tlTerminal hFlush stdout return TerminalLine {..} +printBottomLines :: Terminal -> String -> IO () +printBottomLines term@Terminal {..} str = do + case lines str of + [] -> clearBottomLines term + blines -> do + withMVar termLock $ \_ -> do + atomically $ writeTVar termBottomLines blines + drawBottomLines term + hFlush stdout + +clearBottomLines :: Terminal -> IO () +clearBottomLines Terminal {..} = do + withMVar termLock $ \_ -> do + atomically (readTVar termBottomLines) >>= \case + [] -> return () + _:_ -> do + atomically $ writeTVar termBottomLines [] + putStr $ "\ESC[s\n\ESC[J\ESC[u" + hFlush stdout + +drawBottomLines :: Terminal -> IO () +drawBottomLines Terminal {..} = do + atomically (readTVar termBottomLines) >>= \case + blines@( firstLine : otherLines ) -> do + ( shift ) <- atomically $ do + readTVar termShowPrompt >>= \case + True -> do + prompt <- readTVar termPrompt + ( pre, _ ) <- readTVar termInput + return (displayWidth (prompt <> pre) + 1) + False -> do + return 0 + putStr $ concat + [ "\n\ESC[J", firstLine, concat (map ('\n' :) otherLines) + , "\ESC[", show (length blines), "F" + , "\ESC[", show shift, "G" + ] + [] -> return () + + +displayWidth :: String -> Int +displayWidth = \case + ('\ESC' : '[' : rest) -> displayWidth $ drop 1 $ dropWhile (not . isAlpha) rest + ('\ESC' : _ : rest) -> displayWidth rest + (_ : rest) -> 1 + displayWidth rest + [] -> 0 + + type CompletionFunc m = ( String, String ) -> m ( String, [ Completion ] ) data Completion -- cgit v1.2.3