Utils.hs revision b63d1c8a4e0ea8b68f91c1c1b35b1b735a290113
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess{-# LANGUAGE CPP #-}
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessModule : $Header$
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessDescription : utility functions that can't be found in the libraries
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessCopyright : (c) Klaus Luettich, Uni Bremen 2002-2006
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessLicense : GPLv2 or higher, see LICENSE.txt
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessMaintainer : Christian.Maeder@dfki.de
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessStability : provisional
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPortability : portable
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowenUtility functions that can't be found in the libraries
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen but should be shared across Hets.
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen ( isSingleton
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , trimLeft
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , trimRight
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , nubOrdOn
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , readMaybe
fac8c35bfb158112226ab43ddf84d59daca5dc30nd , mapAccumLM
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen , mapAccumLCM
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen , concatMapM
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , composeMap
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem , splitPaths
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , splitByList
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , numberSuffix
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , basename
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , fileparse
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , stripDir
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh , stripSuffix
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , makeRelativeDesc
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , getEnvSave
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , getEnvDef
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , filterMapWithList
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , timeoutSecs
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , executeProcess
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , timeoutCommand
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , withinDirectory
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , writeTempFile
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , getTempFile
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , getTempFifo
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , readFifo
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , verbMsgLn
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , verbMsgIO
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess , verbMsgIOLn
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport qualified Data.Map as Map
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport qualified Data.Set as Set
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport System.FilePath (joinPath, makeRelative, equalFilePath, takeDirectory)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport System.IO.Error (isEOFError)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess#ifdef UNIX
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport System.Posix.Files (createNamedPipe, unionFileModes,
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess ownerReadMode, ownerWriteMode)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport System.Posix.IO (OpenMode (ReadWrite), defaultFileFlags,
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess openFd, closeFd, fdRead)
d1348237b33bc1755b9f1165eea52317465a7671ndimport Control.Concurrent (threadDelay, forkIO, killThread)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport Control.Concurrent.MVar (MVar, newEmptyMVar, takeMVar, putMVar)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport Control.Exception as Exception
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessimport System.IO.Unsafe (unsafeInterleaveIO)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess{- | Writes the message to the given handle unless the verbosity is less than
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessthe message level. -}
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsg :: Handle -- ^ Output handle
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess -> Int -- ^ global verbosity
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess -> Int -- ^ message level
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess -> String -- ^ message level
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsg hdl v lvl = when (lvl <= v) . hPutStr hdl
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | Same as 'verbMsg' but with a newline at the end
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsgLn :: Handle -> Int -> Int -> String -> IO ()
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsgLn hdl v lvl = when (lvl <= v) . hPutStrLn hdl
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | 'verbMsg' with stdout as handle
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsgIO :: Int -> Int -> String -> IO ()
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsgIO = verbMsg stdout
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | 'verbMsgLn' with stdout as handle
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsgIOLn :: Int -> Int -> String -> IO ()
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessverbMsgIOLn = verbMsgLn stdout
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | replace first (non-empty) sublist with second one in third argument list
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessreplace :: Eq a => [a] -> [a] -> [a] -> [a]
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessreplace sl r = case sl of
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess [] -> error "Common.Utils.replace: empty list"
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess _ -> concat . unfoldr (\ l -> case l of
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess [] -> Nothing
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess hd : tl -> Just $ case stripPrefix sl l of
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess Nothing -> ([hd], tl)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess Just rt -> (r, rt))
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | add indices to a list starting from one
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessnumber :: [a] -> [(a, Int)]
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessnumber = flip zip [1 ..]
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | /O(1)/ test if the set's size is one
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessisSingleton :: Set.Set a -> Bool
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessisSingleton s = Set.size s == 1
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess-- | /O(1)/ test if the set's size is greater one
fac8c35bfb158112226ab43ddf84d59daca5dc30ndhasMany :: Set.Set a -> Bool
d474d8ef01ec5c2a09341cd148851ed383c3287crbowenhasMany s = Set.size s > 1
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh{- | Transform a list @[l1, l2, ... ln]@ to (in sloppy notation)
ba543b319188dc1887607f6d59feddc00e38eee2humbedooh @[[x1, x2, ... xn] | x1 <- l1, x2 <- l2, ... xn <- ln]@
0d0ba3a410038e179b695446bb149cce6264e0abnd (this is just the 'sequence' function!) -}
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedoohcombine :: [[a]] -> [[a]]
0d0ba3a410038e179b695446bb149cce6264e0abndcombine = sequence
0d0ba3a410038e179b695446bb149cce6264e0abnd-- see http://www.haskell.org/pipermail/haskell-cafe/2009-November/069490.html
0d0ba3a410038e179b695446bb149cce6264e0abnd-- | trims a string both on left and right hand side
0d0ba3a410038e179b695446bb149cce6264e0abndtrim :: String -> String
0d0ba3a410038e179b695446bb149cce6264e0abndtrim = trimRight . trimLeft
0d0ba3a410038e179b695446bb149cce6264e0abnd-- | trims a string only on the left side
0d0ba3a410038e179b695446bb149cce6264e0abndtrimLeft :: String -> String
0d0ba3a410038e179b695446bb149cce6264e0abndtrimLeft = dropWhile isSpace
0d0ba3a410038e179b695446bb149cce6264e0abnd-- | trims a string only on the right side
0d0ba3a410038e179b695446bb149cce6264e0abndtrimRight :: String -> String
0d0ba3a410038e179b695446bb149cce6264e0abndtrimRight = foldr (\ c cs -> if isSpace c && null cs then [] else c : cs) ""
5effc8b39fae5cd169d17f342bfc265705840014rbowen{- | The 'nubWith' function accepts as an argument a \"stop list\" update
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowenfunction and an initial stop list. The stop list is a set of list elements
0d0ba3a410038e179b695446bb149cce6264e0abndthat 'nubWith' uses as a filter to remove duplicate elements. The stop list
7fec19672a491661b2fe4b29f685bc7f4efa64d4ndis normally initially empty. The stop list update function is given a list
7fec19672a491661b2fe4b29f685bc7f4efa64d4ndelement a and the current stop list b, and returns 'Nothing' if the element is
7fec19672a491661b2fe4b29f685bc7f4efa64d4ndalready in the stop list, else 'Just' b', where b' is a new stop list updated
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessto contain a. -}
in nubWith f Set.empty
(Map.foldWithKey ( \ i j ->
let k = Map.findWithDefault j j m2 in
path with descents such as ../../test.txt
filterMapWithList = filterMapWithSet . Set.fromList
\ e -> const (threadDelay 100) (e :: Exception.IOException)
readF fd `Exception.catch`
else throwIO (e :: Exception.IOException)