On Thu, 10 Feb 100, Jan Zwanenburg wrote:

> Expected Behaviour:
> User input for the getLine function can be edited with the back-space key.
> The session below should give
>   [104,101,108,108]
> as answer.
>                                                                          
> 
> Observed Behaviour:
> The back-space key is treated just like any other key, so that it occurs in
> the result of the getLine function.
> The session below gives
>   [104,101,108,108,111,8]
> as answer.
> 
> Session transcript:
> getLine >>= \s -> putStr (show (map ord s))
> -- followed by input "hello<BACKSPACE>"

I'm not sure what the haskell report says about getline; I know I've
always assumed getLine was supposed to be a `dumb' function (so backwards
arrows, etc, have the expected visual results on the line being entered in
the terminal, but just get added to the string being constructed rather
than editing it)  and worked around it by using the following code to get
rudimentary editing (with getContents rather than getLine to stop the
auto-editing so that using the arrow keys to insert stuff doesn't result
in the new content overwriting stuff that's still in the string):

---------------------

lArrow = '\001'
rArrow = '\002'
bSpce = '\b'
del = '\DEL'

--hopefully this is lazy and simple enough not to compromise performance
doSymbols "" = ""
doSymbols xs@(x:xs')|"\ESC[C" `isPrefixOf` xs = rArrow:doSymbols (drop 3
xs)
                    |"\ESC[D" `isPrefixOf` xs = lArrow:doSymbols (drop 3
xs)
                    | otherwise = x:doSymbols xs'


--replace this with a monadic IO version when I get time
dspLne :: String -> String -> String -> Int -> (String,String)
dspLne "" ys zs _ = ("",(reverse ys) ++ zs)
dspLne ('\n':_) xs zs _ = ("",(reverse ys) ++ zs)
dspLne (x:xs) (y:ys) zs k
 |x==lArrow = let (acc',res)=dspLne xs ys (y:zs) (k+1)
              in ('\b':acc',res)
 |x==bSpce || x==del = let (acc',res)=dspLne xs ys zs k
                       in ('\b':(zs++" "++(bss!!(k+1))++acc'),res)
dspLne  (x:xs) ys (z:zs) k
 |x==rArrow = let (acc',res)=dspLne xs (z:ys) zs (k-1)
              in (z:acc',res)
dspLne (x:xs) ys zs k = let r@(acc',res)=dspLne xs (x:ys) zs k
                        in if (x == rArrow || x==lArrow) then r
                        else (x:(zs++(bss !! k)++acc'),res)

bss=[] : map ('\b':) bss 

----------------------

use as in

----------------------

getContents >>=
 \s -> let (realtimeUpdateString,finalString)=dspLne (doSymbols s) "" "" 0
       in putStr realtimeUpdateString >>doSomethingWith finalString

----------------------

It's probably not very efficient or aesthetically pleasing (and it's
pre Haskell-98, but I don't think that matters) but it does
work. (Haven't coded with this for a while so I hope I haven't
forgotten anything :-) .) Hope this is helpful as at least a temporary
workaround.

___cheers,_dave________________________________________________________
www.cs.bris.ac.uk/~tweed/pi.htm|ALERT: you are communicating with an
email: [EMAIL PROTECTED]     |unsavoury individual with a copy of gdb
work tel: (0117) 954-5253      |who reverse-engineered a file format.

Reply via email to