Distribution.Utils.Generic

Cabal-2.1.0.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

Contents

- reading and writing files safely
- Unicode
  - Conversions
  - File I/O
  - BOM
  - Misc
- generic utils
- FilePath stuff

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

- withFileContents :: FilePath -> (String -> NoCallStackIO a) -> NoCallStackIO a
- writeFileAtomic :: FilePath -> ByteString -> NoCallStackIO ()
- fromUTF8BS :: ByteString -> String
- fromUTF8LBS :: ByteString -> String
- toUTF8BS :: String -> ByteString
- toUTF8LBS :: String -> ByteString
- readUTF8File :: FilePath -> NoCallStackIO String
- withUTF8FileContents :: FilePath -> (String -> IO a) -> IO a
- writeUTF8File :: FilePath -> String -> NoCallStackIO ()
- ignoreBOM :: String -> String
- normaliseLineEndings :: String -> String
- dropWhileEndLE :: (a -> Bool) -> [a] -> [a]
- takeWhileEndLE :: (a -> Bool) -> [a] -> [a]
- equating :: Eq a => (b -> a) -> b -> b -> Bool
- comparing :: Ord a => (b -> a) -> b -> b -> Ordering
- isInfixOf :: Eq a => [a] -> [a] -> Bool
- intercalate :: [a] -> [[a]] -> [a]
- lowercase :: String -> String
- isAscii :: Char -> Bool
- isAsciiAlpha :: Char -> Bool
- isAsciiAlphaNum :: Char -> Bool
- listUnion :: Ord a => [a] -> [a] -> [a]
- listUnionRight :: Ord a => [a] -> [a] -> [a]
- ordNub :: Ord a => [a] -> [a]
- ordNubBy :: Ord b => (a -> b) -> [a] -> [a]
- ordNubRight :: Ord a => [a] -> [a]
- safeTail :: [a] -> [a]
- unintersperse :: Char -> String -> [String]
- wrapText :: String -> String
- wrapLine :: Int -> [String] -> [[String]]
- unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> m [a]
- spanMaybe :: (a -> Maybe b) -> [a] -> ([b], [a])
- breakMaybe :: (a -> Maybe b) -> [a] -> ([a], Maybe (b, [a]))
- isAbsoluteOnAnyPlatform :: FilePath -> Bool
- isRelativeOnAnyPlatform :: FilePath -> Bool

# 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 #

fromUTF8LBS :: ByteString -> String Source #

toUTF8BS :: String -> ByteString Source #

toUTF8LBS :: String -> ByteString Source #

## 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:

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

    >>> tail $ 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"

isAscii :: Char -> Bool Source #

Ascii characters

isAsciiAlpha :: Char -> Bool Source #

Ascii letters.

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]

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

A total variant of `tail`.

unintersperse :: Char -> String -> [String] Source #

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

# 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.

isRelativeOnAnyPlatform :: FilePath -> Bool Source #

    isRelativeOnAnyPlatform = not . isAbsoluteOnAnyPlatform