--
-- Interactive utility functions
-- Mark P. Jones November 1990
--
-- uses Haskell B. version 0.99.3
--
module Interact(Interactive, skip, end, readln, writeln, readch) where
-- The functions defined in this module provide basic facilities for
-- writing line-oriented interactive programs (i.e. a function mapping
-- an input string to an appropriate output string). These definitions
-- are an enhancement of thos in B+W 7.8
--
-- skip p is an interactive program which consumes no input, produces
-- no output and then behaves like the interactive program p.
-- end is an interactive program which ignores the input and
-- produces no output.
-- writeln txt p is an interactive program which outputs the message txt
-- and then behaves like the interactive program p
-- readch act def is an interactive program which reads the first character c
-- from the input stream and behaves like the interactive
-- program act c. If the input character stream is empty,
-- readch act def prints the default string def and terminates.
--
-- readln p g is an interactive program which prints the prompt p and
-- reads a line (upto the first carriage return, or end of
-- input) from the input stream. It then behaves like g line.
-- Backspace characters included in the input stream are
-- interpretted in the usual way.
type Interactive = String -> String
--- Interactive program combining forms:
skip :: Interactive -> Interactive
skip p inn = p inn -- a dressed up identity function
end :: Interactive
end inn = ""
writeln :: String -> Interactive -> Interactive
writeln txt p inn = txt ++ p inn
readch :: (Char -> Interactive) -> String -> Interactive
readch act def "" = def
readch act def (c:cs) = act c cs
readln :: String -> (String -> Interactive) -> Interactive
readln prompt g inn = prompt ++ lineOut 0 line ++ "\n"
++ g (noBackSpaces line) input'
where line = before '\n' inn
input' = after '\n' inn
after x = tail . dropWhile (x/=)
before x = takeWhile (x/=)
--- Filter out backspaces etc:
rubout :: Char -> Bool
rubout c = (c=='\DEL' || c=='\BS')
lineOut :: Int -> String -> String
lineOut n "" = ""
lineOut n (c:cs)
| n>0 && rubout c = "\BS \BS" ++ lineOut (n-1) cs
| n==0 && rubout c = lineOut 0 cs
| otherwise = c:lineOut (n+1) cs
noBackSpaces :: String -> String
noBackSpaces = reverse . delete 0 . reverse
where delete n "" = ""
delete n (c:cs)
| rubout c = delete (n+1) cs
| n>0 = delete (n-1) cs
| otherwise = c:delete 0 cs
--- End of Interact.hs
|