Cabal-3.2.1.0: A framework for packaging Haskell software
Copyright Isaac Jones Simon Marlow 2003-2004
License BSD3 portions Copyright (c) 2007, Galois Inc.
Maintainer cabal-devel@haskell.org
Portability portable
Safe Haskell None
Language Haskell2010

Distribution.Utils.Generic

Description

A large and somewhat miscellaneous collection of utility functions used throughout the rest of the Cabal lib and in other tools that use the Cabal lib like cabal-install . It has a very simple set of logging actions. It has low level functions for running programs, a bunch of wrappers for various directory and file functions that do extra logging.

Synopsis

reading and writing files safely

withFileContents :: FilePath -> ( String -> NoCallStackIO a) -> NoCallStackIO a Source #

Gets the contents of a file, but guarantee that it gets closed.

The file is read lazily but if it is not fully consumed by the action then the remaining input is truncated and the file is closed.

writeFileAtomic :: FilePath -> ByteString -> NoCallStackIO () Source #

Writes a file atomically.

The file is either written successfully or an IO exception is raised and the original file is left unchanged.

On windows it is not possible to delete a file that is open by a process. This case will give an IO exception but the atomic property is not affected.

Unicode

Conversions

fromUTF8BS :: ByteString -> String Source #

Decode String from UTF8-encoded ByteString

Invalid data in the UTF8 stream (this includes code-points U+D800 through U+DFFF ) will be decoded as the replacement character ( U+FFFD ).

toUTF8BS :: String -> ByteString Source #

Encode String to to UTF8-encoded ByteString

Code-points in the U+D800 - U+DFFF range will be encoded as the replacement character (i.e. U+FFFD ).

validateUTF8 :: ByteString -> Maybe Int Source #

Check that strict ByteString is valid UTF8. Returns 'Just offset' if it's not.

File I/O

readUTF8File :: FilePath -> NoCallStackIO String Source #

Reads a UTF8 encoded text file as a Unicode String

Reads lazily using ordinary readFile .

withUTF8FileContents :: FilePath -> ( String -> IO a) -> IO a Source #

Reads a UTF8 encoded text file as a Unicode String

Same behaviour as withFileContents .

writeUTF8File :: FilePath -> String -> NoCallStackIO () Source #

Writes a Unicode String as a UTF8 encoded text file.

Uses writeFileAtomic , so provides the same guarantees.

BOM

ignoreBOM :: String -> String Source #

Ignore a Unicode byte order mark (BOM) at the beginning of the input

Misc

normaliseLineEndings :: String -> String Source #

Fix different systems silly line ending conventions

generic utils

dropWhileEndLE :: (a -> Bool ) -> [a] -> [a] Source #

dropWhileEndLE p is equivalent to reverse . dropWhile p . reverse , but quite a bit faster. The difference between "Data.List.dropWhileEnd" and this version is that the one in Data.List is strict in elements, but spine-lazy, while this one is spine-strict but lazy in elements. That's what LE stands for - "lazy in elements".

Example:

>>> safeTail $ Data.List.dropWhileEnd (<3) [undefined, 5, 4, 3, 2, 1]
*** Exception: Prelude.undefined
...
>>> safeTail $ dropWhileEndLE (<3) [undefined, 5, 4, 3, 2, 1]
[5,4,3]
>>> take 3 $ Data.List.dropWhileEnd (<3) [5, 4, 3, 2, 1, undefined]
[5,4,3]
>>> take 3 $ dropWhileEndLE (<3) [5, 4, 3, 2, 1, undefined]
*** Exception: Prelude.undefined
...

takeWhileEndLE :: (a -> Bool ) -> [a] -> [a] Source #

takeWhileEndLE p is equivalent to reverse . takeWhile p . reverse , but is usually faster (as well as being easier to read).

equating :: Eq a => (b -> a) -> b -> b -> Bool Source #

comparing :: Ord a => (b -> a) -> b -> b -> Ordering Source #

comparing p x y = compare (p x) (p y)

Useful combinator for use in conjunction with the xxxBy family of functions from Data.List , for example:

  ... sortBy (comparing fst) ...

isInfixOf :: Eq a => [a] -> [a] -> Bool Source #

The isInfixOf function takes two lists and returns True iff the first list is contained, wholly and intact, anywhere within the second.

>>> isInfixOf "Haskell" "I really like Haskell."
True
>>> isInfixOf "Ial" "I really like Haskell."
False

intercalate :: [a] -> [[a]] -> [a] Source #

intercalate xs xss is equivalent to ( concat ( intersperse xs xss)) . It inserts the list xs in between the lists in xss and concatenates the result.

>>> intercalate ", " ["Lorem", "ipsum", "dolor"]
"Lorem, ipsum, dolor"

lowercase :: String -> String Source #

Lower case string

>>> lowercase "Foobar"
"foobar"

isAsciiAlphaNum :: Char -> Bool Source #

Ascii letters and digits.

>>> isAsciiAlphaNum 'a'
True
>>> isAsciiAlphaNum 'ä'
False

listUnion :: Ord a => [a] -> [a] -> [a] Source #

Like "Data.List.union", but has O(n log n) complexity instead of O(n^2) .

listUnionRight :: Ord a => [a] -> [a] -> [a] Source #

A right-biased version of listUnion .

Example:

>>> listUnion [1,2,3,4,3] [2,1,1]
[1,2,3,4,3]
>>> listUnionRight [1,2,3,4,3] [2,1,1]
[4,3,2,1,1]

ordNub :: Ord a => [a] -> [a] Source #

Like nub , but has O(n log n) complexity instead of O(n^2) . Code for ordNub and listUnion taken from Niklas Hambüchen's ordnub package.

ordNubBy :: Ord b => (a -> b) -> [a] -> [a] Source #

Like ordNub and nubBy . Selects a key for each element and takes the nub based on that key.

ordNubRight :: Ord a => [a] -> [a] Source #

A right-biased version of ordNub .

Example:

>>> ordNub [1,2,1] :: [Int]
[1,2]
>>> ordNubRight [1,2,1] :: [Int]
[2,1]

safeHead :: [a] -> Maybe a Source #

A total variant of head .

Since: 3.2.0.0

safeTail :: [a] -> [a] Source #

A total variant of tail .

Since: 3.2.0.0

safeLast :: [a] -> Maybe a Source #

A total variant of last .

Since: 3.2.0.0

safeInit :: [a] -> [a] Source #

A total variant of init .

Since: 3.2.0.0

wrapText :: String -> String Source #

Wraps text to the default line width. Existing newlines are preserved.

wrapLine :: Int -> [ String ] -> [[ String ]] Source #

Wraps a list of words to a list of lines of words of a particular width.

unfoldrM :: Monad m => (b -> m ( Maybe (a, b))) -> b -> m [a] Source #

unfoldr with monadic action.

>>> take 5 $ unfoldrM (\b r -> Just (r + b, b + 1)) (1 :: Int) 2
[3,4,5,6,7]

Since: 2.2

spanMaybe :: (a -> Maybe b) -> [a] -> ([b], [a]) Source #

Like span but with Maybe predicate

>>> spanMaybe listToMaybe [[1,2],[3],[],[4,5],[6,7]]
([1,3],[[],[4,5],[6,7]])
>>> spanMaybe (readMaybe :: String -> Maybe Int) ["1", "2", "foo"]
([1,2],["foo"])

Since: 2.2

breakMaybe :: (a -> Maybe b) -> [a] -> ([a], Maybe (b, [a])) Source #

Like break , but with Maybe predicate

>>> breakMaybe (readMaybe :: String -> Maybe Int) ["foo", "bar", "1", "2", "quu"]
(["foo","bar"],Just (1,["2","quu"]))
>>> breakMaybe (readMaybe :: String -> Maybe Int) ["foo", "bar"]
(["foo","bar"],Nothing)

Since: 2.2

unsnoc :: [a] -> Maybe ([a], a) Source #

The opposite of snoc , which is the reverse of cons

Example:

>>> unsnoc [1, 2, 3]
Just ([1,2],3)
>>> unsnoc []
Nothing

Since: 3.2.0.0

unsnocNE :: NonEmpty a -> ([a], a) Source #

Like unsnoc , but for NonEmpty so without the Maybe

Example:

>>> unsnocNE (1 :| [2, 3])
([1,2],3)
>>> unsnocNE (1 :| [])
([],1)

Since: 3.2.0.0

FilePath stuff

isAbsoluteOnAnyPlatform :: FilePath -> Bool Source #

isAbsoluteOnAnyPlatform and isRelativeOnAnyPlatform are like isAbsolute and isRelative but have platform independent heuristics. The System.FilePath exists in two versions, Windows and Posix. The two versions don't agree on what is a relative path and we don't know if we're given Windows or Posix paths. This results in false positives when running on Posix and inspecting Windows paths, like the hackage server does. System.FilePath.Posix.isAbsolute "C:\hello" == False System.FilePath.Windows.isAbsolute "/hello" == False This means that we would treat paths that start with "/" to be absolute. On Posix they are indeed absolute, while on Windows they are not.

The portable versions should be used when we might deal with paths that are from another OS than the host OS. For example, the Hackage Server deals with both Windows and Posix paths while performing the PackageDescription checks. In contrast, when we run 'cabal configure' we do expect the paths to be correct for our OS and we should not have to use the platform independent heuristics.