HSH 2.0.0 → 2.0.1
raw patch · 3 files changed
+63/−73 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- HSH.ShellEquivs: catBytes :: Int -> (Maybe Integer) -> Handle -> Handle -> IO ()
+ HSH.ShellEquivs: catBytes :: (Maybe Integer) -> Channel -> IO Channel
- HSH.ShellEquivs: catBytesFrom :: Int -> Handle -> (Maybe Integer) -> Handle -> Handle -> IO ()
+ HSH.ShellEquivs: catBytesFrom :: Channel -> (Maybe Integer) -> Channel -> IO Channel
- HSH.ShellEquivs: discard :: Handle -> Handle -> IO ()
+ HSH.ShellEquivs: discard :: Channel -> IO Channel
- HSH.ShellEquivs: tee :: [FilePath] -> ByteString -> IO ByteString
+ HSH.ShellEquivs: tee :: [FilePath] -> Channel -> IO Channel
- HSH.ShellEquivs: teeFIFO :: [FilePath] -> ByteString -> IO ByteString
+ HSH.ShellEquivs: teeFIFO :: [FilePath] -> Channel -> IO Channel
Files
- HSH.cabal +1/−1
- HSH/Channel.hs +3/−2
- HSH/ShellEquivs.hs +59/−70
HSH.cabal view
@@ -1,5 +1,5 @@ Name: HSH-Version: 2.0.0+Version: 2.0.1 License: LGPL Maintainer: John Goerzen <jgoerzen@complete.org> Author: John Goerzen
HSH/Channel.hs view
@@ -28,6 +28,7 @@ import qualified Data.ByteString.Lazy as BSL import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy.UTF8 as UTF8+import qualified System.IO.UTF8 as IOUTF8 import System.IO import Control.Concurrent @@ -40,7 +41,7 @@ chanAsString :: Channel -> IO String chanAsString (ChanString s) = return s chanAsString (ChanBSL s) = return . bsl2str $ s-chanAsString (ChanHandle h) = hGetContents h+chanAsString (ChanHandle h) = IOUTF8.hGetContents h chanAsBSL :: Channel -> IO BSL.ByteString chanAsBSL (ChanString s) = return . str2bsl $ s@@ -54,7 +55,7 @@ {- | Writes the Channel to the given Handle. -} chanToHandle :: Channel -> Handle -> IO ()-chanToHandle (ChanString s) h = hPutStr h s+chanToHandle (ChanString s) h = IOUTF8.hPutStr h s chanToHandle (ChanBSL s) h = BSL.hPut h s chanToHandle (ChanHandle srchdl) desthdl = forkIO copier >> return () where copier = do c <- BSL.hGetContents srchdl
HSH/ShellEquivs.hs view
@@ -84,6 +84,7 @@ import Text.Printf (printf) import Control.Monad (foldM) import System.Directory hiding (createDirectory)+import Control.Exception(evaluate) -- import System.FilePath (splitPath) #ifdef __HSH_POSIX__@@ -136,14 +137,11 @@ {- | Load the specified files and display them, one at a time. The special file @-@ means to display the input. If it is not given,-no input is processed (though a small amount may be read into a buffer).--Unlike the shell cat, @-@ may be given twice. However, if it is, you-will be forcing Haskell to buffer the input.+no input is processed at all. -Note: buffering behavior here is untested. +@-@ may be given a maximum of one time. -See also 'catFromBS', 'catBytes' . -}+See also 'catBytes' . -} catFrom :: [FilePath] -> Channel -> IO Channel catFrom fplist ichan = do r <- foldM foldfunc BSL.empty fplist@@ -155,53 +153,38 @@ fn -> do c <- BSL.readFile fn return (BSL.append accum c) -{- | Copy data in chunks from stdin to stdout, optionally with a fixed-maximum size. Uses strict ByteStrings internally. Uses hSetBuffering-to set the buffering of the input handle to blockbuffering in chunksize-increments as well, but restores original buffering before returning.-See also 'catFrom', 'catBytesFrom' -}-catBytes :: Int -- ^ Preferred chunk size; data will be read in chunks of this size- -> (Maybe Integer) -- ^ Maximum amount of data to transfer- -> Handle -- ^ Handle for input- -> Handle -- ^ Handle for output- -> IO ()-catBytes chunksize count hr = catBytesFrom chunksize hr count hr+{- | Copy data from input to output, optionally with a fixed+maximum size, in bytes. Processes data using ByteStrings internally,+so be aware of any possible UTF-8 conversions. -{- | Generic version of 'catBytes'; reads data from specified Handle, and-ignores stdin. -}+You may wish to use @hSetBuffering h (BlockBuffering Nothing)@ prior to calling+this function for optimal performance. -catBytesFrom :: Int -- ^ Preferred chunk size; data will be read in chunks of this size- -> Handle -- ^ Handle to read from- -> (Maybe Integer) -- ^ Maximum amount of data to transfer- -> Handle -- ^ Handle for input (ignored)- -> Handle -- ^ Handle for output- -> IO ()-catBytesFrom chunksize hr count hignore hw =- do buf <- hGetBuffering hr- catBytesFrom' chunksize hr count hignore hw- hSetBuffering hr buf+See also 'catFrom', 'catBytesFrom' -}+catBytes :: (Maybe Integer) -- ^ Maximum amount of data to transfer+ -> Channel -- ^ Handle for input+ -> IO Channel+catBytes count hr = catBytesFrom hr count hr -catBytesFrom' _ _ (Just 0) _ _ = return ()-catBytesFrom' chunksize hr count hignore hw =- do hSetBuffering hr (BlockBuffering (Just readamount))- case count of - Just x -> if x < 1- then do fail $ "catBytesFrom: count < 0 not supported"- else return ()- _ -> return ()- r <- BS.hGet hr readamount- if BS.null r- then return () -- No more data to read- else do BS.hPutStr hw r- catBytesFrom' chunksize hr (newCount (BS.length r)) hignore hw- where readamount = - case count of- Just x -> fromIntegral $ min x (fromIntegral chunksize)- Nothing -> (fromIntegral chunksize)- newCount newlen = case count of- Nothing -> Nothing- Just x -> Just (x - (fromIntegral newlen))+{- | Generic version of 'catBytes'; reads data from specified Channel, and+ignores stdin.+-} +catBytesFrom :: Channel -- ^ Handle to read from+ -> (Maybe Integer) -- ^ Maximum amount of data to transfer+ -> Channel -- ^ Handle for input (ignored)+ -> IO Channel+catBytesFrom (ChanHandle hr) count cignore =+ case count of+ Nothing -> return (ChanHandle hr)+ Just m -> do c <- BSL.hGet hr (fromIntegral m)+ return (ChanBSL c)+catBytesFrom cinput count cignore =+ case count of+ Nothing -> return cinput+ Just m -> do r <- chanAsBSL cinput+ return (ChanBSL (BSL.take (fromIntegral m) r))+ {- | Takes input, writes it to the specified file, and does not pass it on. The return value is the empty string. See also 'catToBS', 'catToFIFO' -}@@ -266,13 +249,11 @@ cut pos = cutR [pos] {- | Read all input and produce no output. Discards input completely. -}-discard :: Handle -> Handle -> IO ()-discard inh outh =- do eof <- hIsEOF inh- if eof- then return ()- else do BS.hGet inh 4096- discard inh outh+discard :: Channel -> IO Channel+discard inh =+ do c <- chanAsBSL inh+ evaluate (BSL.length c)+ return (ChanString "") {- | Split a list by a given character and select ranges of the resultant lists. @@ -433,27 +414,30 @@ tac = reverse {- | Takes input, writes it to all the specified files, and passes it on.-This function does /NOT' buffer input.+This function does /NOT/ buffer input. See also 'catFrom'. -}-tee :: [FilePath] -> BSL.ByteString -> IO BSL.ByteString+tee :: [FilePath] -> Channel -> IO Channel tee fplist inp = teeBSGeneric (\fp -> openFile fp WriteMode) fplist inp #ifdef __HSH_POSIX__-{- | FIFO-safe version of 'teeBS'.+{- | FIFO-safe version of 'tee'. This call will BLOCK all threads on open until a reader connects. This function is only available on POSIX platforms. -}-teeFIFO :: [FilePath] -> BSL.ByteString -> IO BSL.ByteString+teeFIFO :: [FilePath] -> Channel -> IO Channel teeFIFO fplist inp = teeBSGeneric fifoOpen fplist inp #endif -teeBSGeneric :: (FilePath -> IO Handle) -> [FilePath] -> BSL.ByteString -> IO BSL.ByteString-teeBSGeneric openfunc fplist inp =+teeBSGeneric :: (FilePath -> IO Handle) + -> [FilePath] + -> Channel -> IO Channel+teeBSGeneric openfunc fplist ichan = do handles <- mapM openfunc fplist+ inp <- chanAsBSL ichan resultChunks <- hProcChunks handles (BSL.toChunks inp)- return (BSL.fromChunks resultChunks)+ return (ChanBSL $ BSL.fromChunks resultChunks) where hProcChunks :: [Handle] -> [BS.ByteString] -> IO [BS.ByteString] hProcChunks handles chunks = unsafeInterleaveIO $ case chunks of@@ -484,23 +468,28 @@ uniq :: String -> String uniq = unlines . nub . lines -{- | Double space a file -}-space, unspace :: [String] -> [String]+{- | Double space a file; add an empty line between each line. -}+space :: [String] -> [String] space = intersperse "" -{- | Inverse of double space; drop empty lines -}+{- | Inverse of double 'space'; drop all empty lines. -}+unspace :: [String] -> [String] unspace = filter (not . null) -{- | Convert a string to all upper or lower case -}-lower, upper :: String -> String+{- | Convert a string to all lower case -}+lower :: String -> String lower = map toLower++{- | Convert a string to all upper case -}+upper :: String -> String upper = map toUpper -{- | Count number of lines. wc -l -}-wcL, wcW :: [String] -> [String]+{- | Count number of lines. Like wc -l -}+wcL :: [String] -> [String] wcL inp = [show (genericLength inp :: Integer)] {- | Count number of words in a file (like wc -w) -}+wcW :: [String] -> [String] wcW inp = [show ((genericLength $ words $ unlines inp) :: Integer)] {- Utility function.