microlens-process-0.2.0.0: src/System/Process/Microlens/StdStream.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE Rank2Types #-}
-- |
-- Module : System.Process.Microlens.StdStream
-- Copyright : 2019 Emily Pillmore
-- License : BSD
--
-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>
-- Stability : Experimental
-- Portability : TypeFamilies, Rank2Types
--
-- This module provides the associated optics and combinators
-- for working with 'StdStream' objects. 'StdStream' consists of four
-- cases, for which we provide traversals for each case
--
module System.Process.Microlens.StdStream
( -- * Traversals
_Inherit
, _UseHandle
, _CreatePipe
, _NoStream
-- * Classy Traversals
, IsCreatePipe(..)
, IsInherit(..)
, IsUseHandle(..)
, IsNoStream(..)
-- * Combinators
, inheriting
, piping
, handling
, nostreaming
) where
import Control.Applicative
import Lens.Micro
import System.IO (Handle)
import System.Process
-- $setup
-- >>> import Lens.Micro
-- >>> import qualified System.IO as System (stdin, stdout)
-- >>> import System.Process
-- >>> :set -XTypeApplications
-- >>> :set -XRank2Types
-- ---------------------------------------------------------- --
-- Traversals
-- | A 'Traversal'' into the 'Inherit' structure of a 'StdStream'
--
_Inherit :: Traversal' StdStream StdStream
_Inherit f s = case s of
Inherit -> f s
_ -> pure s
-- | A 'Traversal'' into the 'UseHandle' structure's Handle for a 'StdStream'
--
_UseHandle :: Traversal' StdStream Handle
_UseHandle f s = case s of
UseHandle h -> fmap UseHandle (f h)
_ -> pure s
-- | A 'Traversal'' into the 'CreatePipe' structure of a 'StdStream'
--
_CreatePipe :: Traversal' StdStream StdStream
_CreatePipe f s = case s of
CreatePipe -> f s
_ -> pure s
-- | A 'Traversal'' into the 'NoStream' structure of a 'StdStream'
--
_NoStream :: Traversal' StdStream StdStream
_NoStream f s = case s of
NoStream -> f s
_ -> pure s
-- ---------------------------------------------------------- --
-- Classes
-- | Class constraint proving a type has a prism into an 'Inherit'
-- structure. Any 'StdStream' will have a prism into `Inherit' -
-- it is just an overwrite to 'Inherit'
--
class IsInherit a where
_Inherits :: Traversal' a StdStream
{-# MINIMAL _Inherits #-}
instance IsInherit StdStream where
_Inherits = _Inherit
-- | Class constraint proving a type has a prism into a 'Handle' via
-- a 'UseHandle' structure.
--
class IsUseHandle a where
_UsesHandle :: Traversal' a Handle
{-# MINIMAL _UsesHandle #-}
instance IsUseHandle StdStream where
_UsesHandle = _UseHandle
-- | Class constraint proving a type has a prism into a 'Handle' via
-- a 'UseHandle' structure. Any 'StdStream' will have a prism into
-- 'CreatePipe' - it is just an overwrite to 'CreatePipe'
--
class IsCreatePipe a where
_CreatesPipe :: Traversal' a StdStream
{-# MINIMAL _CreatesPipe #-}
instance IsCreatePipe StdStream where
_CreatesPipe = _CreatePipe
-- | Class constraint proving a type has a prism into a 'Handle' via
-- a 'UseHandle' structure. Any 'StdStream' will have a prism into
-- 'NoStream' - it is just an overwrite to 'NoStream'.
--
class IsNoStream a where
_NoStreams :: Traversal' a StdStream
{-# MINIMAL _NoStreams #-}
instance IsNoStream StdStream where
_NoStreams = _NoStream
-- ---------------------------------------------------------- --
-- Combinators
-- | Given a lens into a 'StdStream', overwrite to 'Inherit' so that
-- the stream inherits from its parent process
--
-- Examples:
--
-- >>> inheriting ($) CreatePipe
-- Inherit
--
inheriting :: Lens' a StdStream -> a -> a
inheriting l = set l Inherit
-- | Given a lens into a 'StdStream', overwrite to 'CreatePipe'.
--
-- Examples:
--
-- >>> piping ($) NoStream
-- CreatePipe
--
piping :: Lens' a StdStream -> a -> a
piping l = set l CreatePipe
-- | Given a lens into a 'StdStream' and a handle, set the handle using
-- 'UseHandle'. Note that this is the only really interesting case for anything
-- with a lens into a handle inculding 'StdStream'.
--
-- Examples:
--
--
-- >>> handling ($) System.stdin $ UseHandle System.stdout
-- UseHandle {handle: <stdin>}
--
-- >>> handling ($) System.stdout Inherit
-- UseHandle {handle: <stdout>}
--
handling :: Lens' a StdStream -> Handle -> a -> a
handling l h = set l (UseHandle h)
-- | Given a lens into a 'StdStream', set to 'NoStream'
--
-- Examples:
--
-- >>> nostreaming ($) Inherit
-- NoStream
--
nostreaming :: Lens' a StdStream -> a -> a
nostreaming l = set l NoStream