{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -Wall #-}

module Control.Process.StdStream
  ( StdStream (..),
    GetStdStream (..),
    HasStdStream (..),
    ReviewStdStream (..),
    AsStdStream (..),
  )
where

import Control.Category (id, (.))
import Control.Lens (Getter, Lens', Prism', Review, prism', unto)
import Data.Maybe (Maybe (Just, Nothing))
import System.IO (Handle)
import System.Process (StdStream (..))

-- $setup
-- >>> import Prelude
-- >>> import Control.Lens
-- >>> import System.IO (stdin, stdout)

-- | Type class for values that can be viewed as a @StdStream@.
--
-- >>> view getStdStream Inherit
-- Inherit
class GetStdStream a where
  getStdStream ::
    Getter a StdStream

-- |
--
-- >>> view getStdStream Inherit
-- Inherit
instance GetStdStream StdStream where
  getStdStream :: Getter StdStream StdStream
getStdStream = (StdStream -> f StdStream) -> StdStream -> f StdStream
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
  {-# INLINE getStdStream #-}

-- | Type class for values with a lens into a @StdStream@.
--
-- >>> view stdStream Inherit
-- Inherit
class (GetStdStream a) => HasStdStream a where
  stdStream ::
    Lens' a StdStream

-- |
--
-- >>> view stdStream Inherit
-- Inherit
-- >>> set stdStream CreatePipe Inherit
-- CreatePipe
instance HasStdStream StdStream where
  stdStream :: Lens' StdStream StdStream
stdStream =
    (StdStream -> f StdStream) -> StdStream -> f StdStream
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

-- | Type class for values that can be constructed from a @StdStream@.
--
-- >>> review reviewStdStream Inherit :: StdStream
-- Inherit
class ReviewStdStream a where
  reviewStdStream ::
    Review a StdStream

-- |
--
-- >>> review reviewStdStream Inherit :: StdStream
-- Inherit
instance ReviewStdStream StdStream where
  reviewStdStream :: Review StdStream StdStream
reviewStdStream = (StdStream -> StdStream)
-> Optic p f StdStream StdStream StdStream StdStream
forall (p :: * -> * -> *) (f :: * -> *) b t s a.
(Profunctor p, Bifunctor p, Functor f) =>
(b -> t) -> Optic p f s t a b
unto StdStream -> StdStream
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
  {-# INLINE reviewStdStream #-}

-- | Type class for values with a prism into a @StdStream@.
--
-- >>> preview _StdStream Inherit
-- Just Inherit
class (ReviewStdStream a) => AsStdStream a where
  _StdStream ::
    Prism' a StdStream
  {-# INLINE _Inherit #-}
  _Inherit ::
    Prism' a ()
  _Inherit =
    p StdStream (f StdStream) -> p a (f a)
forall a. AsStdStream a => Prism' a StdStream
Prism' a StdStream
_StdStream (p StdStream (f StdStream) -> p a (f a))
-> (p () (f ()) -> p StdStream (f StdStream))
-> p () (f ())
-> p a (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p () (f ()) -> p StdStream (f StdStream)
forall a. AsStdStream a => Prism' a ()
Prism' StdStream ()
_Inherit
  {-# INLINE _CreatePipe #-}
  _CreatePipe ::
    Prism' a ()
  _CreatePipe =
    p StdStream (f StdStream) -> p a (f a)
forall a. AsStdStream a => Prism' a StdStream
Prism' a StdStream
_StdStream (p StdStream (f StdStream) -> p a (f a))
-> (p () (f ()) -> p StdStream (f StdStream))
-> p () (f ())
-> p a (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p () (f ()) -> p StdStream (f StdStream)
forall a. AsStdStream a => Prism' a ()
Prism' StdStream ()
_CreatePipe
  {-# INLINE _UseHandle #-}
  _UseHandle ::
    Prism' a Handle
  _UseHandle =
    p StdStream (f StdStream) -> p a (f a)
forall a. AsStdStream a => Prism' a StdStream
Prism' a StdStream
_StdStream (p StdStream (f StdStream) -> p a (f a))
-> (p Handle (f Handle) -> p StdStream (f StdStream))
-> p Handle (f Handle)
-> p a (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Handle (f Handle) -> p StdStream (f StdStream)
forall a. AsStdStream a => Prism' a Handle
Prism' StdStream Handle
_UseHandle
  {-# INLINE _NoStream #-}
  _NoStream ::
    Prism' a ()
  _NoStream =
    p StdStream (f StdStream) -> p a (f a)
forall a. AsStdStream a => Prism' a StdStream
Prism' a StdStream
_StdStream (p StdStream (f StdStream) -> p a (f a))
-> (p () (f ()) -> p StdStream (f StdStream))
-> p () (f ())
-> p a (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p () (f ()) -> p StdStream (f StdStream)
forall a. AsStdStream a => Prism' a ()
Prism' StdStream ()
_NoStream

-- |
--
-- >>> preview _Inherit Inherit
-- Just ()
-- >>> preview _Inherit CreatePipe
-- Nothing
-- >>> preview _CreatePipe CreatePipe
-- Just ()
-- >>> preview _UseHandle (UseHandle stdout)
-- Just {handle: <stdout>}
-- >>> preview _UseHandle Inherit
-- Nothing
-- >>> preview _NoStream NoStream
-- Just ()
-- >>> review _Inherit () :: StdStream
-- Inherit
-- >>> review _CreatePipe () :: StdStream
-- CreatePipe
-- >>> review _UseHandle stdout :: StdStream
-- UseHandle {handle: <stdout>}
-- >>> review _NoStream () :: StdStream
-- NoStream
instance AsStdStream StdStream where
  _StdStream :: Prism' StdStream StdStream
_StdStream =
    p StdStream (f StdStream) -> p StdStream (f StdStream)
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
  _Inherit :: Prism' StdStream ()
_Inherit =
    (() -> StdStream) -> (StdStream -> Maybe ()) -> Prism' StdStream ()
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      (\() -> StdStream
Inherit)
      ( \case
          StdStream
Inherit -> () -> Maybe ()
forall a. a -> Maybe a
Just ()
          StdStream
_ -> Maybe ()
forall a. Maybe a
Nothing
      )
  _CreatePipe :: Prism' StdStream ()
_CreatePipe =
    (() -> StdStream) -> (StdStream -> Maybe ()) -> Prism' StdStream ()
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      (\() -> StdStream
CreatePipe)
      ( \case
          StdStream
CreatePipe -> () -> Maybe ()
forall a. a -> Maybe a
Just ()
          StdStream
_ -> Maybe ()
forall a. Maybe a
Nothing
      )
  _UseHandle :: Prism' StdStream Handle
_UseHandle =
    (Handle -> StdStream)
-> (StdStream -> Maybe Handle) -> Prism' StdStream Handle
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      Handle -> StdStream
UseHandle
      ( \case
          UseHandle Handle
a -> Handle -> Maybe Handle
forall a. a -> Maybe a
Just Handle
a
          StdStream
_ -> Maybe Handle
forall a. Maybe a
Nothing
      )
  _NoStream :: Prism' StdStream ()
_NoStream =
    (() -> StdStream) -> (StdStream -> Maybe ()) -> Prism' StdStream ()
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      (\() -> StdStream
NoStream)
      ( \case
          StdStream
NoStream -> () -> Maybe ()
forall a. a -> Maybe a
Just ()
          StdStream
_ -> Maybe ()
forall a. Maybe a
Nothing
      )