Skip to content

Commit 778d24b

Browse files
committed
add terminal.raw
1 parent 269d04b commit 778d24b

File tree

4 files changed

+37
-34
lines changed

4 files changed

+37
-34
lines changed

Lam.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ library
3636
Lam.TypeChecker
3737
Lam.Utils
3838
Lam.UtilsAgda
39+
Lam.Terminal.Raw
3940
Lam.Terminal.ReadRepl
4041
hs-source-dirs: src
4142
default-language: Haskell2010

src/Lam/Handler.hs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ module Lam.Handler ( replWrapper
1010
import Control.Monad.RWS ( get, put )
1111
import Control.Monad.Except ( liftEither, MonadIO(liftIO), MonadError (..) )
1212
import Data.Map qualified as M
13-
import System.Posix
14-
( stdInput,
15-
getTerminalAttributes,
16-
TerminalState(Immediately) )
1713

1814
import Lam.Context
1915
import Lam.Data
@@ -22,8 +18,8 @@ import Lam.Parser
2218
import Lam.Result
2319
import Lam.TypeChecker
2420
import Lam.Utils
21+
import Lam.Terminal.Raw
2522
import Lam.Terminal.ReadRepl
26-
import System.Posix.Terminal (setTerminalAttributes)
2723

2824
-- TODO: report cyclic dependencies
2925
loadFile :: String -> Result ()
@@ -74,15 +70,15 @@ handleCommand c =
7470
EvalC rExpr -> handleEval rExpr
7571
LoadC path -> loadFile path
7672
ReadC varName -> do
77-
exprS <- liftIO getLine
73+
exprS <- liftIO (readRepl [] "")
7874
isUntyped <- askUntyped
7975
expr <- liftEither (parseRawExpr isUntyped exprS)
8076
handleDefine varName expr
8177
ExitC -> return ()
8278

8379
repl :: CmdHistory -> Result ()
8480
repl h = do
85-
cmdStr <- liftIO (readRepl h)
81+
cmdStr <- liftIO (readRepl h "> ")
8682
let h' = if null cmdStr then h else cmdStr : h
8783
isUntyped <- askUntyped
8884
case parseCommand isUntyped cmdStr of
@@ -95,11 +91,7 @@ repl h = do
9591
repl h'
9692

9793
replWrapper :: Result ()
98-
replWrapper = do
99-
startingAttrs <- liftIO (getTerminalAttributes stdInput)
100-
liftIO (setRawMode startingAttrs)
101-
repl []
102-
liftIO (setTerminalAttributes stdInput startingAttrs Immediately)
94+
replWrapper = runInRawMode (repl [])
10395

10496
handleFile :: String -> Result ()
10597
handleFile fName = do

src/Lam/Terminal/Raw.hs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module Lam.Terminal.Raw where
2+
3+
import System.Posix.Terminal
4+
import System.Posix (stdInput)
5+
import Control.Monad.Cont (MonadIO, liftIO)
6+
7+
withRawMode :: TerminalAttributes -> TerminalAttributes
8+
withRawMode attrs =
9+
let withoutMode' = flip withoutMode in
10+
foldl (\a fn -> fn a) attrs
11+
[ withoutMode' EnableEcho
12+
, withoutMode' ProcessInput
13+
, withoutMode' ExtendedFunctions
14+
]
15+
16+
setRawMode :: TerminalAttributes -> IO ()
17+
setRawMode attrs = do
18+
let rawAttrs = withRawMode attrs
19+
setTerminalAttributes stdInput rawAttrs Immediately
20+
21+
runInRawMode :: MonadIO m => m a -> m a
22+
runInRawMode m = do
23+
attrs <- liftIO (getTerminalAttributes stdInput)
24+
liftIO (setRawMode attrs)
25+
a <- m
26+
liftIO (setTerminalAttributes stdInput attrs Immediately)
27+
return a

src/Lam/Terminal/ReadRepl.hs

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import System.Console.ANSI
55
import GHC.IO.Handle
66
import GHC.IO.StdHandles
77
import System.IO (hReady)
8-
import System.Posix.Terminal
9-
import System.Posix (stdInput)
108

119
type CmdHistory = [String]
1210

@@ -22,21 +20,20 @@ update [] _ _ = []
2220
update (_ : tl) 0 a = a : tl
2321
update (hd : tl) i a = hd : update tl (i - 1) a
2422

25-
readRepl :: CmdHistory -> IO String
26-
readRepl originalHistory =
23+
readRepl :: CmdHistory -> String -> IO String
24+
readRepl originalHistory prompt =
2725
loop 0 0 ("" : originalHistory)
2826
where
2927
loop pos hisPos history = do
3028
let cmd = history !! hisPos
3129
setCursorColumn 0
3230
clearLine
33-
putStr ("> " ++ cmd)
34-
setCursorColumn (pos + 2)
31+
putStr (prompt ++ cmd)
32+
setCursorColumn (pos + length prompt)
3533
hFlush stdout
3634
k <- getKey
3735
case k of
38-
"\n" ->
39-
putStr "\n" >> return cmd
36+
"\n" -> putStr "\n" >> return cmd
4037
"\ESC[A" -> -- up
4138
let hisPos' = min (hisPos + 1) (length history - 1) in
4239
let pos' = length (history !! hisPos') in
@@ -57,17 +54,3 @@ readRepl originalHistory =
5754
let cmd' = take pos cmd ++ k ++ drop pos cmd in
5855
let history' = update history hisPos cmd' in
5956
loop (min (pos + 1) (length cmd')) hisPos history'
60-
61-
setRawMode :: TerminalAttributes -> IO ()
62-
setRawMode attrs = do
63-
let rawAttrs = withRawMode attrs
64-
setTerminalAttributes stdInput rawAttrs Immediately
65-
66-
withRawMode :: TerminalAttributes -> TerminalAttributes
67-
withRawMode attrs =
68-
let withoutMode' = flip withoutMode in
69-
foldl (\a f -> f a) attrs
70-
[ withoutMode' EnableEcho
71-
, withoutMode' ProcessInput
72-
, withoutMode' ExtendedFunctions
73-
]

0 commit comments

Comments
 (0)