In: Computer Science
<Haskell>
Using getCh, define an action readLine :: IO String that behaves in the same way as getLine, except that it also permits the delete key to be used to remove characters.
Hint: the delete character is ’\DEL’, and the control character for moving the cursor back one space is ’\b’.
Solution
> getLine' :: IO String
> getLine' = do x <- getChar
> if x == '\n' then
> return []
> else
> do xs <- getLine
> return (x:xs)
Note: `getLine` above allows for the use of the backspace
key.
It works as you'd expect. Further, GHCI won't allow me to enter
'\DEL'
as a character.
As a result, on windows, this solution doesn't do anything
that
`getLine` doesn't despite the added complexity.
On a linux system, the behaviour is thus:
> getLine'
this^?is
"this\DELis"
> readLine
this^?is
"thiis"
> readLine :: IO String
> readLine = get ""
> get :: String -> IO String
> get xs = do x <- getChar
> case x of
> '\n' -> return xs
> '\DEL' -> if null xs then
> get xs
> else
> do putStr "\ESC[1D \ESC[ID"
> get $ init xs
> _ -> get $ xs ++ [x]
> getLine' :: IO String
> getLine' = do x <- getChar
> if x == '\n' then
> return []
> else
> do xs <- getLine
> return (x:xs)
Note: `getLine` above allows for the use of the backspace
key.
It works as you'd expect. Further, GHCI won't allow me to enter
'\DEL'
as a character.
As a result, on windows, this solution doesn't do anything
that
`getLine` doesn't despite the added complexity.
On a linux system, the behaviour is thus:
> getLine'
this^?is
"this\DELis"
> readLine
this^?is
"thiis"
> readLine :: IO String
> readLine = get ""
> get :: String -> IO String
> get xs = do x <- getChar
> case x of
> '\n' -> return xs
> '\DEL' -> if null xs then
> get xs
> else
> do putStr "\ESC[1D \ESC[ID"
> get $ init xs
> _ -> get $ xs ++ [x]
---
all the best