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.
13 {-# OPTIONS -#include "cbits/ghcReadline.h" #-}
19 rlBindKey, rlAddDefun,
22 rlGetLineBuffer, rlSetLineBuffer,
23 rlGetPoint, rlSetPoint,
29 rlPrompt, rlTerminalName, rlSetReadlineName, rlGetReadlineName
35 import PackedString ( unpackCString )
40 --#include <readline/readline.h>
44 type RlCallbackFunction =
45 (Int -> -- Numeric Argument
46 KeyCode -> -- KeyCode of pressed Key
50 %***************************************************************************
52 \subsection[Readline-Functions]{Main Readline Functions}
54 %***************************************************************************
57 readline :: String -> -- Prompt String
58 IO String -- Returned line
60 --ToDo: Get the "Live register in _casm_GC_ " bug fixed
61 -- this stops us passing the prompt string to readline directly :-(
62 -- litstr <- _casm_GC_ ``%r = readline(%0);'' prompt
63 _casm_ ``rl_prompt_hack = (char*)realloc(rl_prompt_hack, %1);
64 strcpy (rl_prompt_hack,%0);''
65 prompt (length prompt)
66 litstr <- _casm_GC_ ``%r = readline (rl_prompt_hack);''
67 if (litstr == ``NULL'')
68 then fail (userError "Readline has read EOF")
70 let str = unpackCString litstr
71 _casm_ ``free(%0);'' litstr
75 addHistory :: String -- String to enter in history
77 addHistory str = _ccall_ add_history str
80 rlBindKey :: KeyCode -> -- Key to Bind to
81 RlCallbackFunction -> -- Function to exec on execution
84 if (0 > key) || (key > 255) then
85 fail (userError "Invalid ASCII Key Code, must be in range 0.255")
87 addCbackEntry (key,cback)
88 _casm_ `` rl_bind_key((KeyCode)%0,&genericRlCback); '' key
92 i.e. add the (KeyCode,RlCallbackFunction) key to the assoc. list and register
93 the generic callback for this KeyCode.
95 The entry point that $genericRlCback$ calls would then read the
96 global variables $current\_i$ and $current\_kc$ and do a lookup:
99 rlAddDefun :: String -> -- Function Name
100 RlCallbackFunction -> -- Function to call
101 KeyCode -> -- Key to bind to, or -1 for no bind
103 rlAddDefun name cback key =
104 if (0 > key) || (key > 255) then
105 fail (userError "Invalid ASCII Key Code, must be in range 0..255")
107 addCbackEntry (key, cback)
108 _casm_ ``rl_add_defun (%0, &genericRlCback, (KeyCode)%1);'' name key
113 The C function $genericRlCallback$ puts the callback arguments into
114 global variables and enters the Haskell world through the
115 $haskellRlEntry$ function. Before exiting, the Haskell function will
116 deposit its result in the global varariable $rl\_return$.
118 In the Haskell action that is invoked via $enterStablePtr$, a match
119 between the Keycode in $current\_kc$ and the Haskell callback needs to
120 be made. To essentially keep the same assoc. list of (KeyCode,cback
121 function) as Readline does, we make use of yet another global variable
126 createCbackList :: [(KeyCode,RlCallbackFunction)] -> PrimIO ()
128 #ifndef __PARALLEL_HASKELL__
129 makeStablePtr ls >>= \ stable_ls ->
130 _casm_ `` cbackList=(StgStablePtr)%0; '' stable_ls
132 error "createCbackList: not available for Parallel Haskell"
135 getCbackList :: PrimIO [(KeyCode,RlCallbackFunction)]
137 #ifndef __PARALLEL_HASKELL__
138 _casm_ `` %r=(StgStablePtr)cbackList; '' >>= \ stable_ls ->
139 deRefStablePtr stable_ls
141 error "getCbackList: not available for Parallel Haskell"
144 setCbackList :: [(KeyCode,RlCallbackFunction)] -> PrimIO ()
146 #ifndef __PARALLEL_HASKELL__
147 _casm_ `` %r=(StgStablePtr)cbackList; '' >>= \ old_stable_ls ->
148 freeStablePtr old_stable_ls >>
151 error "setCbackList: not available for Parallel Haskell"
154 addCbackEntry :: (KeyCode,RlCallbackFunction) -> IO ()
155 addCbackEntry entry = do
157 setCbackList (entry:ls)
160 The above functions allows us to query and augment the assoc. list in
165 invokeRlCback :: IO ()
167 kc <- _casm_ `` %r=(KeyCode)current_kc; ''
168 narg <- _casm_ `` %r=(int)current_narg; ''
171 (case (dropWhile (\ (key,_) -> kc/=key) ls) of
173 ((_,cback):_) -> cback narg kc
175 _casm_ `` rl_return=(int)%0; '' ret_val
179 Finally, we need to initialise this whole, ugly machinery:
182 initRlCbacks :: PrimIO ()
185 #ifndef __PARALLEL_HASKELL__
186 createCbackList [] >>
187 makeStablePtr (invokeRlCback) >>= \ stable_f ->
188 _casm_ `` haskellRlEntry=(StgStablePtr)%0; '' stable_f >>= \ () ->
191 error "initRlCbacks: not available for Parallel Haskell"
196 %***************************************************************************
198 \subsection[Readline-Globals]{Global Readline Variables}
200 %***************************************************************************
202 These are the global variables required by the readline lib. Need to
203 find a way of making these read/write from the Haskell side. Should
204 they be in the IO Monad, should they be Mutable Variables?
208 rlGetLineBuffer :: IO String
210 litstr <- _casm_ ``%r = rl_line_buffer;''
211 return (unpackCString litstr)
213 rlSetLineBuffer :: String -> IO ()
214 rlSetLineBuffer str = _casm_ ``rl_line_buffer = %0;'' str
218 rlGetPoint = _casm_ ``%r = rl_point;''
220 rlSetPoint :: Int -> IO ()
221 rlSetPoint point = _casm_ ``rl_point = %0;'' point
224 rlGetEnd = _casm_ ``%r = rl_end;''
226 rlSetEnd :: Int -> IO ()
227 rlSetEnd end = _casm_ ``rl_end = %0;'' end
230 rlGetMark = _casm_ ``%r = rl_mark;''
232 rlSetMark :: Int -> IO ()
233 rlSetMark mark = _casm_ ``rl_mark = %0;'' mark
235 rlSetDone :: Bool -> IO ()
236 rlSetDone True = _casm_ ``rl_done = %0;'' 1
237 rlSetDone False = _casm_ ``rl_done = %0;'' 0
239 rlPendingInput :: KeyCode -> IO ()
240 rlPendingInput key = primIOToIO (_casm_ ``rl_pending_input = %0;'' key)
242 rlPrompt :: IO String
244 litstr <- _casm_ ``%r = rl_readline_name;''
245 return (unpackCString litstr)
247 rlTerminalName :: IO String
249 litstr <- _casm_ ``%r = rl_terminal_name;''
250 return (unpackCString litstr)
253 rlGetReadlineName :: IO String
254 rlGetReadlineName = do
255 litstr <- _casm_ ``%r = rl_readline_name;''
256 return (unpackCString litstr)
258 rlSetReadlineName :: String -> IO ()
259 rlSetReadlineName str = _casm_ ``rl_readline_name = %0;'' str
264 -- The following two were taken from PreludeStdIO stdin/stdout
267 rlInStream = unsafePerformPrimIO (
268 newMVar >>= \ handle ->
269 _ccall_ getLock (``rl_instream''::Addr) 0 >>= \ rc ->
271 0 -> putMVar handle ClosedHandle
272 1 -> putMVar handle (ReadHandle ``rl_instream'' Nothing False)
273 _ -> constructError >>= \ ioError ->
274 putMVar handle (ErrorHandle ioError)
280 rlOutStream :: Handle
281 rlOutStream = unsafePerformPrimIO (
282 newMVar >>= \ handle ->
283 _ccall_ getLock (``rl_outstream''::Addr) 1 >>= \ rc ->
285 0 -> putMVar handle ClosedHandle
286 1 -> putMVar handle (WriteHandle ``rl_outstream'' Nothing False)
287 _ -> constructError >>= \ ioError ->
288 putMVar handle (ErrorHandle ioError)
298 -- rlStartupHook :: RlCallBackFunction -> IO ()
300 rlInitialize :: IO ()
303 rlSetReadlineName pname
304 _casm_ ``rl_prompt_hack = (char*)malloc(1);''