module Restyler.Prelude
    ( module X
    , module Restyler.Prelude
    )
where

-- Prefer Bifunctor first/second not Arrow
import RIO as X hiding (exitSuccess, first, second)

import Control.Error.Util as X (hush, note)
import Control.Monad.Extra as X (eitherM, fromMaybeM, maybeM)
import Data.Bifunctor as X (first, second)
import Data.Bitraversable as X (Bitraversable, bimapM)
import Data.Functor.Syntax as X ((<$$>))
import GitHub.Data as X (Id, Name, URL(..), getUrl, mkId, mkName, untagName)
import RIO.Char as X (isSpace)
import RIO.List as X
    ( dropWhileEnd
    , find
    , genericLength
    , headMaybe
    , maximumByMaybe
    , maximumMaybe
    , minimumByMaybe
    , minimumMaybe
    )
import RIO.Text as X (pack, unpack)
import Safe as X (fromJustNote)

import qualified Data.Foldable as F
import qualified Data.HashMap.Lazy as HM
import qualified Data.Set as Set
import qualified RIO.Text as T

-- Apparently they fixed a space leak in Data.List's version :shrug:
import qualified Data.Text.Internal.Functions as List (intersperse)

firstM :: (Bitraversable t, Applicative f) => (a -> f a') -> t a b -> f (t a' b)
firstM :: (a -> f a') -> t a b -> f (t a' b)
firstM f :: a -> f a'
f = (a -> f a') -> (b -> f b) -> t a b -> f (t a' b)
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bimapM a -> f a'
f b -> f b
forall (f :: * -> *) a. Applicative f => a -> f a
pure

secondM
    :: (Bitraversable t, Applicative f) => (b -> f b') -> t a b -> f (t a b')
secondM :: (b -> f b') -> t a b -> f (t a b')
secondM = (a -> f a) -> (b -> f b') -> t a b -> f (t a b')
forall (t :: * -> * -> *) (f :: * -> *) a c b d.
(Bitraversable t, Applicative f) =>
(a -> f c) -> (b -> f d) -> t a b -> f (t c d)
bimapM a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | Like @'withReader'@ for @'RIO'@
withRIO :: (env' -> env) -> RIO env a -> RIO env' a
withRIO :: (env' -> env) -> RIO env a -> RIO env' a
withRIO f :: env' -> env
f m :: RIO env a
m = do
    env
env <- (env' -> env) -> RIO env' env
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks env' -> env
f
    env -> RIO env a -> RIO env' a
forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
runRIO env
env RIO env a
m

-- | Decode known-valid UTF-8
--
-- Uses @'lenientDecode'@:
--
-- Replace an invalid input byte with the Unicode replacement character U+FFFD.
--
decodeUtf8 :: ByteString -> Text
decodeUtf8 :: ByteString -> Text
decodeUtf8 = OnDecodeError -> ByteString -> Text
T.decodeUtf8With OnDecodeError
T.lenientDecode

displayIntercalated :: Display a => Utf8Builder -> [a] -> Utf8Builder
displayIntercalated :: Utf8Builder -> [a] -> Utf8Builder
displayIntercalated sep :: Utf8Builder
sep = [Utf8Builder] -> Utf8Builder
forall a. Monoid a => [a] -> a
mconcat ([Utf8Builder] -> Utf8Builder)
-> ([a] -> [Utf8Builder]) -> [a] -> Utf8Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Utf8Builder -> [Utf8Builder] -> [Utf8Builder]
forall a. a -> [a] -> [a]
List.intersperse Utf8Builder
sep ([Utf8Builder] -> [Utf8Builder])
-> ([a] -> [Utf8Builder]) -> [a] -> [Utf8Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Utf8Builder) -> [a] -> [Utf8Builder]
forall a b. (a -> b) -> [a] -> [b]
map a -> Utf8Builder
forall a. Display a => a -> Utf8Builder
display

handles :: MonadUnliftIO m => [Handler m a] -> m a -> m a
handles :: [Handler m a] -> m a -> m a
handles = (m a -> [Handler m a] -> m a) -> [Handler m a] -> m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip m a -> [Handler m a] -> m a
forall (m :: * -> *) a.
MonadUnliftIO m =>
m a -> [Handler m a] -> m a
catches

handleTo
    :: (MonadUnliftIO m, Exception e1, Exception e2) => (e1 -> e2) -> m a -> m a
handleTo :: (e1 -> e2) -> m a -> m a
handleTo f :: e1 -> e2
f = (e1 -> m a) -> m a -> m a
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
(e -> m a) -> m a -> m a
handle (e2 -> m a
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO (e2 -> m a) -> (e1 -> e2) -> e1 -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e1 -> e2
f)

tryTo :: (MonadUnliftIO m, Exception e) => (e -> b) -> m a -> m (Either b a)
tryTo :: (e -> b) -> m a -> m (Either b a)
tryTo f :: e -> b
f = (Either e a -> Either b a) -> m (Either e a) -> m (Either b a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((e -> b) -> Either e a -> Either b a
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first e -> b
f) (m (Either e a) -> m (Either b a))
-> (m a -> m (Either e a)) -> m a -> m (Either b a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> m (Either e a)
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try

intersects :: (Foldable t1, Foldable t2, Ord a) => t1 a -> t2 a -> Bool
intersects :: t1 a -> t2 a -> Bool
intersects a :: t1 a
a b :: t2 a
b = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Set a -> Bool
forall a. Set a -> Bool
Set.null (Set a -> Bool) -> Set a -> Bool
forall a b. (a -> b) -> a -> b
$ Set a -> Set a -> Set a
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set a
a' Set a
b'
  where
    a' :: Set a
a' = [a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList ([a] -> Set a) -> [a] -> Set a
forall a b. (a -> b) -> a -> b
$ t1 a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList t1 a
a
    b' :: Set a
b' = [a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList ([a] -> Set a) -> [a] -> Set a
forall a b. (a -> b) -> a -> b
$ t2 a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList t2 a
b

-- | Inverse of @'any'@
none :: Foldable t => (a -> Bool) -> t a -> Bool
none :: (a -> Bool) -> t a -> Bool
none p :: a -> Bool
p = Bool -> Bool
not (Bool -> Bool) -> (t a -> Bool) -> t a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Bool) -> t a -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any a -> Bool
p

insertIfMissing :: (Eq k, Hashable k) => k -> v -> HashMap k v -> HashMap k v
insertIfMissing :: k -> v -> HashMap k v -> HashMap k v
insertIfMissing = (v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
HM.insertWith ((v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v)
-> (v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
forall a b. (a -> b) -> a -> b
$ (v -> v -> v) -> v -> v -> v
forall a b c. (a -> b -> c) -> b -> a -> c
flip v -> v -> v
forall a b. a -> b -> a
const

with :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t a)
with :: t a -> (a -> f b) -> f (t a)
with ma :: t a
ma f :: a -> f b
f = t a -> (a -> f a) -> f (t a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for t a
ma ((a -> f a) -> f (t a)) -> (a -> f a) -> f (t a)
forall a b. (a -> b) -> a -> b
$ \a :: a
a -> a
a a -> f b -> f a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ a -> f b
f a
a