Alastair,

> A third solution which I haven't tried yet but might try soon is to
> write a dumb (possibly very dumb) implementation of Readline in pure
> Haskell and have Readline use the dumb implementation if the C library
> and headers aren't available.  I'm in two minds about this approach
> because the semantics of my dumb version would be a fairly poor match
> for the semantics of the real thing.

To save you the trouble, I've already written a (very) dumb simple
line editor in Haskell as a replacement for Readline for machines or
compilers which don't have it.  The source has been part of "hmake
interactive" for some time, and is also attached below if you want
to steal and modify it.

Regards,
    Malcolm

----cut here----
{- Either use ReadLine, or a dumb replacement.
-- Copyright Malcolm Wallace, 2000.
-- Open source licensed under the same terms as nhc98.
-}
module SimpleLineEditor
  ( getLineEdited       --      :: {- [String] -> -} IO String
  , delChars            --      :: String -> IO ()
  ) where

import IO
import Monad (when)
import Char
#if USE_READLINE
import Readline
#endif

delChars :: String -> IO ()
delChars []     = return ()
delChars (_:xs) = do putStr "\BS \BS"
                     delChars xs

-- getLineEdited relies on having the terminal in non-buffered mode,
-- therefore please ensure that `hSetBuffering NoBuffering' is called
-- before using this.

#if USE_READLINE

getLineEdited :: String -> IO (Maybe String)
getLineEdited prompt = do
  ms <- readline prompt
  case ms of 
    Nothing -> return ms
    Just s  -> when (not (all isSpace s)) (addHistory s) >> return ms

#else

getLineEdited :: String -> {- [String]-> -}  IO (Maybe String)
getLineEdited prompt {-history-} = putStr prompt >> gl "" 0
  where
  gl s 0 = do           -- s is accumulated line, 0 is cursor position
    c <- hGetChar stdin
    case c of
      '\n'   -> return (Just (reverse s))
      '\DEL' -> do delChars "^?"
                   gl s 0
      '\BS'  -> do delChars "^H"
                   if not (null s) then do
                       putStr ("\BS")
                       gl s 1
                     else gl s 0
  --  '\^J'  -> do delChars "^J"
  --               putChar '\n'
  --               return (reverse s)
      '\^K'  -> do putChar '\n'
                   return (Just "")
      '\^L'  -> do delChars "^L"
                   gl s 0
      c      -> gl (c:s) 0

  gl s n = do           -- s is accumulated line, n(/=0) is cursor position
    c <- hGetChar stdin
    case c of
      '\n'   -> return (Just (reverse s))
      '\DEL' -> do let n1 = n-1
                   delChars "^?"
                   putStr (reverse (take n1 s) ++ " ")
                   putStr (replicate (n1+1) '\BS')
                   gl (take n1 s ++ drop n s) n1
      '\BS'  -> do let n1 = n+1
                   delChars "^H"
                   if n1 <= length s then do
                       putStr (reverse (take n s)++" ")
                       putStr (replicate (n1+1) '\BS')
                       gl s n1
                     else do
                       putStr (reverse s++" ")
                       putStr (replicate (n+1) '\BS')
                       gl s n
  --  '\^J'  -> do delChars "^J"
  --               putStr (reverse (take n s))
  --               putChar '\n'
                   return (Just (reverse s))
      '\^K'  -> do putChar '\n'
                   return (Just "")
      '\^L'  -> do let n1 = n-1
                   delChars "^L"
                   putStr (reverse (take n s))
                   putStr (replicate n1 '\BS')
                   gl s n1
      c      -> do putStr (reverse (take n s))
                   putStr (replicate n '\BS')
                   gl (take n s ++ c: drop n s) n

#endif -- USE_READLINE

_______________________________________________
Glasgow-haskell-bugs mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to