2 % (c) The GRASP/AQUA Project, Glasgow University, 1995-1996
4 \section[Readline]{GNU Readline Library Bindings}
6 This module attempts to provide a better line based editing facility
7 for Haskell programmers by providing access to the GNU Readline
8 library. Related to this are bindings for the GNU History library
9 which can be found in History (at some point in the future :-).
11 Original version by Darren Moffat
12 Heavily modified in 1999 by Sven Panne <Sven.Panne@informatik.uni-muenchen.de>
16 * This binding is still *very* incomplete... Volunteers?
18 * The GHC User's Guide section on Readline is not up-to-date anymore,
19 the flags you need are: -syslib misc -syslib posix -lreadline -ltermcap
20 (or -lncurses on some Linux systems)
23 {-# OPTIONS -#include <readline/readline.h> -#include <readline/history.h> #-}
29 rlBindKey, rlAddDefun,
32 rlGetLineBuffer, rlSetLineBuffer,
33 rlGetPoint, rlSetPoint,
39 rlPrompt, rlTerminalName,
40 rlGetReadlineName, rlSetReadlineName,
42 rlInStream, rlOutStream
46 import ByteArray(ByteArray)
48 import CString(packString, unpackCStringIO)
50 import IOExts(IORef, newIORef, readIORef, writeIORef, unsafePerformIO, freeHaskellFunctionPtr)
51 import Maybe(fromMaybe)
53 import Posix(intToFd, fdToHandle)
54 import System(getProgName)
56 -- SUP: Haskell has closures and I've got no clue about the return value,
57 -- so a better type for the callbacks is probably
58 -- Int {- Numeric Arg -} -> IO ()
62 type RlCallbackFunction =
63 (Int -> -- Numeric Argument
64 KeyCode -> -- KeyCode of pressed Key
65 IO Int) -- What's this?
68 %***************************************************************************
70 \subsection[Readline-Functions]{Main Readline Functions}
72 %***************************************************************************
76 rlInitialize = rlSetReadlineName =<< getProgName
78 foreign import "free" unsafe free :: Addr -> IO ()
79 foreign import "readline" unsafe readlineAux :: ByteArray Int -> IO Addr
81 readline :: String -- Prompt String
82 -> IO (Maybe String) -- Just returned line or Nothing if EOF
84 cstr <- readlineAux (packString prompt)
87 else do str <- unpackCStringIO cstr
91 foreign import "add_history" unsafe add_history :: ByteArray Int -> IO ()
93 addHistory :: String -- String to enter in history
95 addHistory = add_history . packString
98 foreign export dynamic mkRlCallback :: (Int -> Int -> IO Int) -> IO Addr
99 foreign import "rl_bind_key" rl_bind_key :: Int -> Addr -> IO Int
101 rlBindKey :: KeyCode -- Key to Bind to
102 -> RlCallbackFunction -- Function to exec on execution
104 rlBindKey key cback = do
105 cbAddr <- mkRlCallback (\n k -> cback n (chr k))
106 ok <- rl_bind_key (ord key) cbAddr
107 if ok /= 0 then wrongKeyCode else addCbackEntry key cbAddr
109 foreign import "rl_add_defun" unsafe rl_add_defun :: ByteArray Int -> Addr -> Int -> IO Int
111 rlAddDefun :: String -> -- Function Name
112 RlCallbackFunction -> -- Function to call
113 Maybe KeyCode -> -- Key to bind to
115 rlAddDefun name cback mbKey = do
116 cbAddr <- mkRlCallback (\n k -> cback n (chr k))
117 ok <- rl_add_defun (packString name) cbAddr (maybe (-1) ord mbKey)
118 when (ok /= 0) wrongKeyCode
120 -- Don't know how this should ever happen with KeyCode = Char
121 wrongKeyCode :: IO ()
122 wrongKeyCode = ioError (userError "Invalid ASCII Key Code, must be in range 0..255")
124 -- Global hacking for freeing callbacks
126 theCbackTable :: IORef [(KeyCode,Addr)]
127 theCbackTable = unsafePerformIO (newIORef [])
129 addCbackEntry :: KeyCode -> Addr -> IO ()
130 addCbackEntry key cbAddr = do
131 cbackTable <- readIORef theCbackTable
132 maybe (return ()) freeHaskellFunctionPtr (lookup key cbackTable)
133 writeIORef theCbackTable
134 ((key,cbAddr) : [ entry | entry@(k,_) <- cbackTable, k /= key ])
139 %***************************************************************************
141 \subsection[Readline-Globals]{Global Readline Variables}
143 %***************************************************************************
145 These are the global variables required by the readline lib. Need to
146 find a way of making these read/write from the Haskell side. Should
147 they be in the IO Monad, should they be Mutable Variables?
151 rlGetLineBuffer :: IO String
152 rlGetLineBuffer = unpackCStringIO =<< _casm_ ``%r = rl_line_buffer;''
154 rlSetLineBuffer :: String -> IO ()
155 rlSetLineBuffer str = _casm_ ``rl_line_buffer = %0;'' str
158 rlGetPoint = _casm_ ``%r = rl_point;''
160 rlSetPoint :: Int -> IO ()
161 rlSetPoint point = _casm_ ``rl_point = %0;'' point
164 rlGetEnd = _casm_ ``%r = rl_end;''
166 rlSetEnd :: Int -> IO ()
167 rlSetEnd end = _casm_ ``rl_end = %0;'' end
170 rlGetMark = _casm_ ``%r = rl_mark;''
172 rlSetMark :: Int -> IO ()
173 rlSetMark mark = _casm_ ``rl_mark = %0;'' mark
175 rlSetDone :: Bool -> IO ()
176 rlSetDone False = _casm_ ``rl_done = %0;'' (0::Int)
177 rlSetDone True = _casm_ ``rl_done = %0;'' (1::Int)
179 rlPendingInput :: KeyCode -> IO ()
180 rlPendingInput key = _casm_ ``rl_pending_input = %0;'' key
182 rlPrompt :: IO String
183 rlPrompt = unpackCStringIO =<< _casm_ ``%r = rl_readline_name;''
185 rlTerminalName :: IO String
186 rlTerminalName = unpackCStringIO =<< _casm_ ``%r = rl_terminal_name;''
188 rlGetReadlineName :: IO String
189 rlGetReadlineName = unpackCStringIO =<< _casm_ ``%r = rl_readline_name;''
191 rlSetReadlineName :: String -> IO ()
192 rlSetReadlineName str = _casm_ ``rl_readline_name = %0;'' str
195 rlInStream = unsafePerformIO (fdToHandle (intToFd ``fileno(rl_instream)''))
197 rlOutStream :: Handle
198 rlOutStream = unsafePerformIO (fdToHandle (intToFd ``fileno(rl_outstream)''))
205 main = do rlInitialize
206 rlBindKey '\^X' (\nargc kc -> do print (nargc,kc); return 0)
208 where loop = maybe (putStrLn "Qapla'!")
209 (\reply -> do unless (null reply) (addHistory reply)
210 putStrLn (reply ++ "... pItlh!")
211 loop) =<< readline "nuqneH, ghunwI'? "