Shellac-readline (empty) → 0.9
raw patch · 4 files changed
+183/−0 lines, 4 filesdep +Shellacdep +basedep +haskell98build-type:Customsetup-changed
Dependencies added: Shellac, base, haskell98, readline
Files
- LICENSE +23/−0
- Setup.hs +3/−0
- Shellac-readline.cabal +25/−0
- src/System/Console/Shell/Backend/Readline.hs +132/−0
+ LICENSE view
@@ -0,0 +1,23 @@+Copyright 2005-2006, Robert Dockins.+All Rights Reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++- Redistribution of source code must retain the above copyright notice,+this list of conditions and the following disclamer.++- Redistribution in binary form must reproduce the above copyright notice,+this list of conditions and the following disclamer in the documentation+and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ Shellac-readline.cabal view
@@ -0,0 +1,25 @@+Name: Shellac-readline+Version: 0.9+License: BSD3+License-File: LICENSE+Author: Robert Dockins+Maintainer: robdockins AT fastmail DOT fm+Category: User Interfaces+Stability: Beta+Synopsis: Readline backend module for Shellac+Description:+ This package provides a Shellac backend based on the GNU readline+ library. This backend features all the line editing capabilities+ provided by readline, as well as command completion and command+ history features.+Hs-Source-Dirs:+ src+Build-Depends:+ base >= 1.0,+ haskell98 >= 1.0,+ readline >= 1.0,+ Shellac >= 0.9+Exposed-modules:+ System.Console.Shell.Backend.Readline+Extensions:+ ForeignFunctionInterface
+ src/System/Console/Shell/Backend/Readline.hs view
@@ -0,0 +1,132 @@+{-+ - + - Copyright 2005-2007, Robert Dockins.+ - + -}++{- | This module implements a Shellac backend based on the GNU readline+ and GNU history modules. For readline, we use the bindings+ from the standard library. For history, we import directily using+ FFI. This Shellac backend supports command completion, history buffer+ and all the line editing and character binding features of GNU readline.++ Beware that while the code for this Shellac binding is licensed under a BSD3+ license, GNU readline itself is licensed under the GPL. This means that your+ project needs to be GPL compatible for this Shellac backend to be useful to you.+-}+++module System.Console.Shell.Backend.Readline+( readlineBackend+) where++import System.IO ( stdin, stdout, stderr, hFlush, hPutStr, hPutStrLn, hGetChar+ , hSetBuffering, hGetBuffering+ , BufferMode(..)+ )+import Foreign.Ptr ( Ptr )+import Foreign.C ( CInt, CString, withCString )+import Foreign.C.Error ( Errno, eOK, errnoToIOError )+import Foreign.Storable ( peek )++import qualified Control.Exception as Ex+import qualified System.Console.Readline as RL++import System.Console.Shell.Backend ++readlineBackend :: ShellBackend ()+readlineBackend = ShBackend+ { initBackend = doReadlineInit+ , shutdownBackend = \_ -> doReadlineShutdown+ , outputString = \_ -> readlineOutput+ , flushOutput = \_ -> hFlush stdout+ , getInput = \_ -> RL.readline+ , getSingleChar = \_ -> readlineGetSingleChar+ , addHistory = \_ -> RL.addHistory+ , getWordBreakChars = \_ -> RL.getBasicWordBreakCharacters+ , setWordBreakChars = \_ -> RL.setBasicWordBreakCharacters+ , onCancel = \_ -> hPutStrLn stdout "canceled..."+ , setAttemptedCompletionFunction = \_ -> readlineCompletionFunction+ , setDefaultCompletionFunction = \_ -> RL.setCompletionEntryFunction+ , completeFilename = \_ -> RL.filenameCompletionFunction+ , completeUsername = \_ -> RL.usernameCompletionFunction+ , clearHistoryState = \_ -> doClearHistoryState+ , setMaxHistoryEntries = \_ -> doSetMaxHistoryEntries+ , getMaxHistoryEntries = \_ -> doGetMaxHistoryEntries+ , readHistory = \_ -> doReadHistory+ , writeHistory = \_ -> doWriteHistory+ }+++readlineCompletionFunction :: CompletionFunction -> IO ()+readlineCompletionFunction f = RL.setAttemptedCompletionFunction (Just complete)++ where complete word begin end = do+ buffer <- RL.getLineBuffer+ let before = take begin buffer+ let after = drop end buffer++ f (before,word,after)+++readlineGetSingleChar :: String -> IO (Maybe Char)+readlineGetSingleChar prompt = do+ hPutStr stdout prompt+ hFlush stdout+ Ex.bracket (hGetBuffering stdin) (hSetBuffering stdin) $ \_ -> do+ hSetBuffering stdin NoBuffering+ c <- hGetChar stdin+ hPutStrLn stdout ""+ return (Just c)++foreign import ccall "readline/history.h clear_history" clear_history :: IO ()+foreign import ccall "readline/history.h stifle_history" stifle_history :: CInt -> IO ()+foreign import ccall "readline/history.h read_history" read_history :: CString -> IO Errno+foreign import ccall "readline/history.h write_history" write_history :: CString -> IO Errno+foreign import ccall "readline/history.h &history_max_entries" history_max_entries :: Ptr CInt+foreign import ccall "readline/history.h using_history" using_history :: IO ()++doReadlineInit :: IO ()+doReadlineInit = do+ using_history+ return ()++doReadlineShutdown :: IO ()+doReadlineShutdown = do+ return ()++doClearHistoryState :: IO ()+doClearHistoryState = clear_history++doSetMaxHistoryEntries :: Int -> IO ()+doSetMaxHistoryEntries m = stifle_history (fromIntegral m)++doGetMaxHistoryEntries :: IO Int+doGetMaxHistoryEntries = peek history_max_entries >>= return . fromIntegral++doReadHistory :: FilePath -> IO ()+doReadHistory path = do+ err <- withCString path read_history+ if err == eOK+ then return ()+ else ioError $ errnoToIOError + "System.Console.Shell.Backend.Readline.doReadHistory"+ err+ Nothing+ (Just path)++doWriteHistory :: FilePath -> IO ()+doWriteHistory path = do+ err <- withCString path write_history+ if err == eOK+ then return ()+ else ioError $ errnoToIOError+ "System.Console.Shell.Backend.Readline.doWriteHistory"+ err+ Nothing+ (Just path)++readlineOutput :: BackendOutput -> IO ()+readlineOutput (RegularOutput str) = hPutStr stdout str+readlineOutput (InfoOutput str) = hPutStr stdout str+readlineOutput (ErrorOutput str) = hPutStr stderr str