module System.Console.Editline(
EditLine(),
elInit,
reset,
elGets,
setPrompt,
Editor(..),
setEditor
) where
import Foreign.C
import Foreign.ForeignPtr
import Foreign.Ptr
import Foreign.Marshal
import Foreign.Storable (peek)
import Control.Monad
data EDITLINE
newtype EditLine = EditLine (ForeignPtr EDITLINE)
withEditLine :: EditLine -> (Ptr EDITLINE -> IO a) -> IO a
withEditLine (EditLine fp) = withForeignPtr fp
elInit :: String
-> IO EditLine
elInit prog = do
el <- withCString prog el_init_from_term
fmap EditLine $ newForeignPtr el_end el
foreign import ccall el_init_from_term :: CString -> IO (Ptr EDITLINE)
foreign import ccall "&" el_end :: FunPtr (Ptr EDITLINE -> IO ())
reset :: EditLine -> IO ()
reset el = withEditLine el el_reset
foreign import ccall el_reset :: Ptr EDITLINE -> IO ()
elGets :: EditLine -> IO (Maybe String)
elGets el = withEditLine el $ \el_p -> alloca $ \count_p -> do
result <- el_gets el_p count_p
count <- fmap fromEnum $ peek count_p
if result == nullPtr
then return Nothing
else fmap Just $ peekCStringLen (result, count)
foreign import ccall el_gets :: Ptr EDITLINE -> Ptr CInt -> IO CString
foreign import ccall el_set_prompt :: Ptr EDITLINE -> FunPtr PromptFunc -> IO CInt
setPrompt :: EditLine -> IO String -> IO ()
setPrompt el f = withEditLine el $ \el_p -> do
f_ptr <- mkPromptFunc $ \_ -> f >>= newCString
el_set_prompt el_p f_ptr
return ()
type PromptFunc = Ptr EDITLINE -> IO CString
foreign import ccall "wrapper" mkPromptFunc :: PromptFunc -> IO (FunPtr PromptFunc)
data Editor = Vi | Emacs
editorString :: Editor -> String
editorString Vi = "vi"
editorString Emacs = "emacs"
setEditor :: EditLine -> Editor -> IO ()
setEditor el editor = withEditLine el $ \el_p ->
withCString (editorString editor) $ \ed_str ->
el_set_editor el_p ed_str >> return ()
foreign import ccall el_set_editor :: Ptr EDITLINE -> CString -> IO CInt