{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module HaskellCI.Prelude (
    module Prelude.Compat,
    module X,
    module HaskellCI.Prelude,
    ) where

import Prelude.Compat hiding (head, tail)

import Algebra.Lattice         as X (BoundedJoinSemiLattice (..), BoundedLattice, BoundedMeetSemiLattice (..), Lattice (..))
import Control.Applicative     as X (liftA2, (<|>))
import Control.Exception       as X (Exception (..), IOException, handle)
import Control.Monad           as X (ap, unless, void, when)
import Control.Monad.Catch     as X (MonadCatch, MonadMask, MonadThrow)
import Control.Monad.IO.Class  as X (MonadIO (..))
import Data.Bifoldable         as X (Bifoldable (..))
import Data.Bifunctor          as X (Bifunctor (..))
import Data.Binary             as X (Binary)
import Data.Bitraversable      as X (Bitraversable (..), bifoldMapDefault, bimapDefault)
import Data.ByteString         as X (ByteString)
import Data.Char               as X (isSpace, isUpper, toLower)
import Data.Coerce             as X (coerce)
import Data.Either             as X (partitionEithers)
import Data.Foldable           as X (for_, toList, traverse_)
import Data.Foldable.WithIndex as X (ifoldr)
import Data.Function           as X (on)
import Data.Functor.Compat     as X ((<&>))
import Data.Functor.Identity   as X (Identity (..))
import Data.List               as X (foldl', intercalate, isPrefixOf, nub, stripPrefix, tails)
import Data.List.NonEmpty      as X (NonEmpty (..), groupBy)
import Data.Maybe              as X (fromMaybe, isJust, isNothing, listToMaybe, mapMaybe)
import Data.Proxy              as X (Proxy (..))
import Data.Set                as X (Set)
import Data.String             as X (IsString (fromString))
import Data.Text               as X (Text)
import Data.Typeable           as X (Typeable)
import Data.Void               as X (Void)
import GHC.Generics            as X (Generic)
import Network.URI             as X (URI, parseURI, uriToString)
import Numeric.Natural         as X (Natural)
import Text.Read               as X (readMaybe)

import Data.Generics.Lens.Lite  as X (field)
import Distribution.Compat.Lens as X (over, toListOf, (&), (.~), (^.))

import Distribution.Parsec        as X (simpleParsec)
import Distribution.Pretty        as X (prettyShow)
import Distribution.Utils.Generic as X (fromUTF8BS, toUTF8BS)
import Distribution.Version       as X (Version, VersionRange, anyVersion, mkVersion, noVersion)

import qualified Distribution.Compat.CharParsing as C
import qualified Distribution.Parsec             as C
import qualified Distribution.Pretty             as C
import qualified Distribution.Version            as C
import qualified Text.PrettyPrint                as PP

import Data.Functor.WithIndex.Instances ()

-------------------------------------------------------------------------------
-- Extras
-------------------------------------------------------------------------------

mapped :: forall f a b. Functor f => (a -> Identity b) -> f a -> Identity (f b)
mapped :: forall (f :: * -> *) a b.
Functor f =>
(a -> Identity b) -> f a -> Identity (f b)
mapped = ((a -> b) -> f a -> f b)
-> (a -> Identity b) -> f a -> Identity (f b)
forall a b. Coercible a b => a -> b
coerce ((a -> b) -> f a -> f b
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap :: (a -> b) -> f a -> f b)

head :: NonEmpty a -> a
head :: forall a. NonEmpty a -> a
head (a
x :| [a]
_) = a
x

-- $setup
-- >>> import Text.Read (readMaybe)

-- | Return the part after the first argument
--
-- >>> afterInfix "BAR" "FOOBAR XYZZY"
-- Just " XYZZY"
--
afterInfix :: Eq a => [a] -> [a] -> Maybe [a]
afterInfix :: forall a. Eq a => [a] -> [a] -> Maybe [a]
afterInfix [a]
needle [a]
haystack = ([a] -> Maybe [a]) -> [[a]] -> Maybe [a]
forall a b. (a -> Maybe b) -> [a] -> Maybe b
findMaybe ([a] -> [a] -> Maybe [a]
forall a. Eq a => [a] -> [a] -> Maybe [a]
afterPrefix [a]
needle) ([a] -> [[a]]
forall a. [a] -> [[a]]
tails [a]
haystack)

-- |
--
-- >>> afterPrefix "FOO" "FOOBAR"
-- Just "BAR"
--
afterPrefix :: Eq a => [a] -> [a] -> Maybe [a]
afterPrefix :: forall a. Eq a => [a] -> [a] -> Maybe [a]
afterPrefix [a]
needle [a]
haystack
    | [a]
needle [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [a]
haystack = [a] -> Maybe [a]
forall a. a -> Maybe a
Just (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
needle) [a]
haystack)
    | Bool
otherwise                    = Maybe [a]
forall a. Maybe a
Nothing

-- |
--
-- >>> findMaybe readMaybe ["foo", "1", "bar"] :: Maybe Int
-- Just 1
--
findMaybe :: (a -> Maybe b) -> [a] -> Maybe b
findMaybe :: forall a b. (a -> Maybe b) -> [a] -> Maybe b
findMaybe a -> Maybe b
f = (a -> Maybe b -> Maybe b) -> Maybe b -> [a] -> Maybe b
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
a Maybe b
b -> a -> Maybe b
f a
a Maybe b -> Maybe b -> Maybe b
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe b
b) Maybe b
forall a. Maybe a
Nothing

-- | Whether two ranges are equivalent.
equivVersionRanges :: C.VersionRange -> C.VersionRange -> Bool
equivVersionRanges :: VersionRange -> VersionRange -> Bool
equivVersionRanges = ([VersionInterval] -> [VersionInterval] -> Bool)
-> (VersionRange -> [VersionInterval])
-> VersionRange
-> VersionRange
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on [VersionInterval] -> [VersionInterval] -> Bool
forall a. Eq a => a -> a -> Bool
(==) VersionRange -> [VersionInterval]
C.asVersionIntervals

-------------------------------------------------------------------------------
-- Orphans
-------------------------------------------------------------------------------

instance Lattice VersionRange where
    /\ :: VersionRange -> VersionRange -> VersionRange
(/\) = VersionRange -> VersionRange -> VersionRange
C.intersectVersionRanges
    \/ :: VersionRange -> VersionRange -> VersionRange
(\/) = VersionRange -> VersionRange -> VersionRange
C.unionVersionRanges

instance C.Parsec Natural where
    parsec :: forall (m :: * -> *). CabalParsing m => m Natural
parsec = m Natural
forall (m :: * -> *) a. (CharParsing m, Integral a) => m a
C.integral

instance C.Pretty Natural where
    pretty :: Natural -> Doc
pretty = String -> Doc
PP.text (String -> Doc) -> (Natural -> String) -> Natural -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> String
forall a. Show a => a -> String
show