-- -- 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