{-# language GeneralizedNewtypeDeriving #-}

module Nix.String
  ( NixString
  , getStringContext
  , mkNixString
  , StringContext(..)
  , ContextFlavor(..)
  , NixLikeContext(..)
  , NixLikeContextValue(..)
  , toNixLikeContext
  , fromNixLikeContext
  , hasContext
  , intercalateNixString
  , getStringNoContext
  , ignoreContext
  , mkNixStringWithoutContext
  , mkNixStringWithSingletonContext
  , modifyNixContents
  , WithStringContext
  , WithStringContextT(..)
  , extractNixString
  , addStringContext
  , addSingletonStringContext
  , runWithStringContextT
  , runWithStringContextT'
  , runWithStringContext
  , runWithStringContext'
  )
where




import           Nix.Prelude             hiding ( Type, TVar )
import           Control.Monad.Writer           ( WriterT(..), MonadWriter(tell))
import qualified Data.HashMap.Lazy             as M
import qualified Data.HashSet                  as S
import qualified Data.Text                     as Text
import           Nix.Expr.Types                 ( VarName(..)
                                                , AttrSet
                                                )


-- * Types

-- ** Context

-- | A Nix 'StringContext' ...
data StringContext =
  StringContext
    { StringContext -> ContextFlavor
getStringContextFlavor :: !ContextFlavor
    , StringContext -> VarName
getStringContextPath   :: !VarName
    }
  deriving (StringContext -> StringContext -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StringContext -> StringContext -> Bool
$c/= :: StringContext -> StringContext -> Bool
== :: StringContext -> StringContext -> Bool
$c== :: StringContext -> StringContext -> Bool
Eq, Eq StringContext
StringContext -> StringContext -> Bool
StringContext -> StringContext -> Ordering
StringContext -> StringContext -> StringContext
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: StringContext -> StringContext -> StringContext
$cmin :: StringContext -> StringContext -> StringContext
max :: StringContext -> StringContext -> StringContext
$cmax :: StringContext -> StringContext -> StringContext
>= :: StringContext -> StringContext -> Bool
$c>= :: StringContext -> StringContext -> Bool
> :: StringContext -> StringContext -> Bool
$c> :: StringContext -> StringContext -> Bool
<= :: StringContext -> StringContext -> Bool
$c<= :: StringContext -> StringContext -> Bool
< :: StringContext -> StringContext -> Bool
$c< :: StringContext -> StringContext -> Bool
compare :: StringContext -> StringContext -> Ordering
$ccompare :: StringContext -> StringContext -> Ordering
Ord, Int -> StringContext -> ShowS
[StringContext] -> ShowS
StringContext -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StringContext] -> ShowS
$cshowList :: [StringContext] -> ShowS
show :: StringContext -> String
$cshow :: StringContext -> String
showsPrec :: Int -> StringContext -> ShowS
$cshowsPrec :: Int -> StringContext -> ShowS
Show, forall x. Rep StringContext x -> StringContext
forall x. StringContext -> Rep StringContext x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep StringContext x -> StringContext
$cfrom :: forall x. StringContext -> Rep StringContext x
Generic)

instance Hashable StringContext

-- | A 'ContextFlavor' describes the sum of possible derivations for string contexts
data ContextFlavor
  = DirectPath
  | AllOutputs
  | DerivationOutput !Text
  deriving (Int -> ContextFlavor -> ShowS
[ContextFlavor] -> ShowS
ContextFlavor -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ContextFlavor] -> ShowS
$cshowList :: [ContextFlavor] -> ShowS
show :: ContextFlavor -> String
$cshow :: ContextFlavor -> String
showsPrec :: Int -> ContextFlavor -> ShowS
$cshowsPrec :: Int -> ContextFlavor -> ShowS
Show, ContextFlavor -> ContextFlavor -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ContextFlavor -> ContextFlavor -> Bool
$c/= :: ContextFlavor -> ContextFlavor -> Bool
== :: ContextFlavor -> ContextFlavor -> Bool
$c== :: ContextFlavor -> ContextFlavor -> Bool
Eq, Eq ContextFlavor
ContextFlavor -> ContextFlavor -> Bool
ContextFlavor -> ContextFlavor -> Ordering
ContextFlavor -> ContextFlavor -> ContextFlavor
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ContextFlavor -> ContextFlavor -> ContextFlavor
$cmin :: ContextFlavor -> ContextFlavor -> ContextFlavor
max :: ContextFlavor -> ContextFlavor -> ContextFlavor
$cmax :: ContextFlavor -> ContextFlavor -> ContextFlavor
>= :: ContextFlavor -> ContextFlavor -> Bool
$c>= :: ContextFlavor -> ContextFlavor -> Bool
> :: ContextFlavor -> ContextFlavor -> Bool
$c> :: ContextFlavor -> ContextFlavor -> Bool
<= :: ContextFlavor -> ContextFlavor -> Bool
$c<= :: ContextFlavor -> ContextFlavor -> Bool
< :: ContextFlavor -> ContextFlavor -> Bool
$c< :: ContextFlavor -> ContextFlavor -> Bool
compare :: ContextFlavor -> ContextFlavor -> Ordering
$ccompare :: ContextFlavor -> ContextFlavor -> Ordering
Ord, forall x. Rep ContextFlavor x -> ContextFlavor
forall x. ContextFlavor -> Rep ContextFlavor x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ContextFlavor x -> ContextFlavor
$cfrom :: forall x. ContextFlavor -> Rep ContextFlavor x
Generic)

instance Hashable ContextFlavor

newtype NixLikeContext =
  NixLikeContext
    { NixLikeContext -> AttrSet NixLikeContextValue
getNixLikeContext :: AttrSet NixLikeContextValue
    }
  deriving (NixLikeContext -> NixLikeContext -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NixLikeContext -> NixLikeContext -> Bool
$c/= :: NixLikeContext -> NixLikeContext -> Bool
== :: NixLikeContext -> NixLikeContext -> Bool
$c== :: NixLikeContext -> NixLikeContext -> Bool
Eq, Eq NixLikeContext
NixLikeContext -> NixLikeContext -> Bool
NixLikeContext -> NixLikeContext -> Ordering
NixLikeContext -> NixLikeContext -> NixLikeContext
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NixLikeContext -> NixLikeContext -> NixLikeContext
$cmin :: NixLikeContext -> NixLikeContext -> NixLikeContext
max :: NixLikeContext -> NixLikeContext -> NixLikeContext
$cmax :: NixLikeContext -> NixLikeContext -> NixLikeContext
>= :: NixLikeContext -> NixLikeContext -> Bool
$c>= :: NixLikeContext -> NixLikeContext -> Bool
> :: NixLikeContext -> NixLikeContext -> Bool
$c> :: NixLikeContext -> NixLikeContext -> Bool
<= :: NixLikeContext -> NixLikeContext -> Bool
$c<= :: NixLikeContext -> NixLikeContext -> Bool
< :: NixLikeContext -> NixLikeContext -> Bool
$c< :: NixLikeContext -> NixLikeContext -> Bool
compare :: NixLikeContext -> NixLikeContext -> Ordering
$ccompare :: NixLikeContext -> NixLikeContext -> Ordering
Ord, Int -> NixLikeContext -> ShowS
[NixLikeContext] -> ShowS
NixLikeContext -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NixLikeContext] -> ShowS
$cshowList :: [NixLikeContext] -> ShowS
show :: NixLikeContext -> String
$cshow :: NixLikeContext -> String
showsPrec :: Int -> NixLikeContext -> ShowS
$cshowsPrec :: Int -> NixLikeContext -> ShowS
Show, forall x. Rep NixLikeContext x -> NixLikeContext
forall x. NixLikeContext -> Rep NixLikeContext x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NixLikeContext x -> NixLikeContext
$cfrom :: forall x. NixLikeContext -> Rep NixLikeContext x
Generic)

data NixLikeContextValue =
  NixLikeContextValue
    { NixLikeContextValue -> Bool
nlcvPath :: !Bool
    , NixLikeContextValue -> Bool
nlcvAllOutputs :: !Bool
    , NixLikeContextValue -> [Text]
nlcvOutputs :: ![Text]
    }
  deriving (Int -> NixLikeContextValue -> ShowS
[NixLikeContextValue] -> ShowS
NixLikeContextValue -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NixLikeContextValue] -> ShowS
$cshowList :: [NixLikeContextValue] -> ShowS
show :: NixLikeContextValue -> String
$cshow :: NixLikeContextValue -> String
showsPrec :: Int -> NixLikeContextValue -> ShowS
$cshowsPrec :: Int -> NixLikeContextValue -> ShowS
Show, NixLikeContextValue -> NixLikeContextValue -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NixLikeContextValue -> NixLikeContextValue -> Bool
$c/= :: NixLikeContextValue -> NixLikeContextValue -> Bool
== :: NixLikeContextValue -> NixLikeContextValue -> Bool
$c== :: NixLikeContextValue -> NixLikeContextValue -> Bool
Eq, Eq NixLikeContextValue
NixLikeContextValue -> NixLikeContextValue -> Bool
NixLikeContextValue -> NixLikeContextValue -> Ordering
NixLikeContextValue -> NixLikeContextValue -> NixLikeContextValue
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NixLikeContextValue -> NixLikeContextValue -> NixLikeContextValue
$cmin :: NixLikeContextValue -> NixLikeContextValue -> NixLikeContextValue
max :: NixLikeContextValue -> NixLikeContextValue -> NixLikeContextValue
$cmax :: NixLikeContextValue -> NixLikeContextValue -> NixLikeContextValue
>= :: NixLikeContextValue -> NixLikeContextValue -> Bool
$c>= :: NixLikeContextValue -> NixLikeContextValue -> Bool
> :: NixLikeContextValue -> NixLikeContextValue -> Bool
$c> :: NixLikeContextValue -> NixLikeContextValue -> Bool
<= :: NixLikeContextValue -> NixLikeContextValue -> Bool
$c<= :: NixLikeContextValue -> NixLikeContextValue -> Bool
< :: NixLikeContextValue -> NixLikeContextValue -> Bool
$c< :: NixLikeContextValue -> NixLikeContextValue -> Bool
compare :: NixLikeContextValue -> NixLikeContextValue -> Ordering
$ccompare :: NixLikeContextValue -> NixLikeContextValue -> Ordering
Ord, forall x. Rep NixLikeContextValue x -> NixLikeContextValue
forall x. NixLikeContextValue -> Rep NixLikeContextValue x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NixLikeContextValue x -> NixLikeContextValue
$cfrom :: forall x. NixLikeContextValue -> Rep NixLikeContextValue x
Generic)

instance Semigroup NixLikeContextValue where
  NixLikeContextValue
a <> :: NixLikeContextValue -> NixLikeContextValue -> NixLikeContextValue
<> NixLikeContextValue
b =
    NixLikeContextValue
      { nlcvPath :: Bool
nlcvPath       = NixLikeContextValue -> Bool
nlcvPath       NixLikeContextValue
a Bool -> Bool -> Bool
|| NixLikeContextValue -> Bool
nlcvPath       NixLikeContextValue
b
      , nlcvAllOutputs :: Bool
nlcvAllOutputs = NixLikeContextValue -> Bool
nlcvAllOutputs NixLikeContextValue
a Bool -> Bool -> Bool
|| NixLikeContextValue -> Bool
nlcvAllOutputs NixLikeContextValue
b
      , nlcvOutputs :: [Text]
nlcvOutputs    = NixLikeContextValue -> [Text]
nlcvOutputs    NixLikeContextValue
a forall a. Semigroup a => a -> a -> a
<> NixLikeContextValue -> [Text]
nlcvOutputs    NixLikeContextValue
b
      }

instance Monoid NixLikeContextValue where
  mempty :: NixLikeContextValue
mempty = Bool -> Bool -> [Text] -> NixLikeContextValue
NixLikeContextValue Bool
False Bool
False forall a. Monoid a => a
mempty


-- ** StringContext accumulator

-- | A monad for accumulating string context while producing a result string.
newtype WithStringContextT m a =
  WithStringContextT
    (WriterT (S.HashSet StringContext) m a )
  deriving (forall a b. a -> WithStringContextT m b -> WithStringContextT m a
forall a b.
(a -> b) -> WithStringContextT m a -> WithStringContextT m b
forall (m :: * -> *) a b.
Functor m =>
a -> WithStringContextT m b -> WithStringContextT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> WithStringContextT m a -> WithStringContextT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> WithStringContextT m b -> WithStringContextT m a
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> WithStringContextT m b -> WithStringContextT m a
fmap :: forall a b.
(a -> b) -> WithStringContextT m a -> WithStringContextT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> WithStringContextT m a -> WithStringContextT m b
Functor, forall a. a -> WithStringContextT m a
forall a b.
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m a
forall a b.
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
forall a b.
WithStringContextT m (a -> b)
-> WithStringContextT m a -> WithStringContextT m b
forall a b c.
(a -> b -> c)
-> WithStringContextT m a
-> WithStringContextT m b
-> WithStringContextT m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall {m :: * -> *}.
Applicative m =>
Functor (WithStringContextT m)
forall (m :: * -> *) a.
Applicative m =>
a -> WithStringContextT m a
forall (m :: * -> *) a b.
Applicative m =>
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m a
forall (m :: * -> *) a b.
Applicative m =>
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
forall (m :: * -> *) a b.
Applicative m =>
WithStringContextT m (a -> b)
-> WithStringContextT m a -> WithStringContextT m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> WithStringContextT m a
-> WithStringContextT m b
-> WithStringContextT m c
<* :: forall a b.
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m a
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m a
*> :: forall a b.
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
liftA2 :: forall a b c.
(a -> b -> c)
-> WithStringContextT m a
-> WithStringContextT m b
-> WithStringContextT m c
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> WithStringContextT m a
-> WithStringContextT m b
-> WithStringContextT m c
<*> :: forall a b.
WithStringContextT m (a -> b)
-> WithStringContextT m a -> WithStringContextT m b
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
WithStringContextT m (a -> b)
-> WithStringContextT m a -> WithStringContextT m b
pure :: forall a. a -> WithStringContextT m a
$cpure :: forall (m :: * -> *) a.
Applicative m =>
a -> WithStringContextT m a
Applicative, forall a. a -> WithStringContextT m a
forall a b.
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
forall a b.
WithStringContextT m a
-> (a -> WithStringContextT m b) -> WithStringContextT m b
forall {m :: * -> *}. Monad m => Applicative (WithStringContextT m)
forall (m :: * -> *) a. Monad m => a -> WithStringContextT m a
forall (m :: * -> *) a b.
Monad m =>
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
forall (m :: * -> *) a b.
Monad m =>
WithStringContextT m a
-> (a -> WithStringContextT m b) -> WithStringContextT m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> WithStringContextT m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> WithStringContextT m a
>> :: forall a b.
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
WithStringContextT m a
-> WithStringContextT m b -> WithStringContextT m b
>>= :: forall a b.
WithStringContextT m a
-> (a -> WithStringContextT m b) -> WithStringContextT m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
WithStringContextT m a
-> (a -> WithStringContextT m b) -> WithStringContextT m b
Monad, forall (m :: * -> *) a. Monad m => m a -> WithStringContextT m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
lift :: forall (m :: * -> *) a. Monad m => m a -> WithStringContextT m a
$clift :: forall (m :: * -> *) a. Monad m => m a -> WithStringContextT m a
MonadTrans, MonadWriter (S.HashSet StringContext))

type WithStringContext = WithStringContextT Identity


-- ** NixString

data NixString =
  NixString
    { NixString -> HashSet StringContext
getStringContext :: !(S.HashSet StringContext)
    , NixString -> Text
getStringContent :: !Text
    }
  deriving (NixString -> NixString -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NixString -> NixString -> Bool
$c/= :: NixString -> NixString -> Bool
== :: NixString -> NixString -> Bool
$c== :: NixString -> NixString -> Bool
Eq, Eq NixString
NixString -> NixString -> Bool
NixString -> NixString -> Ordering
NixString -> NixString -> NixString
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NixString -> NixString -> NixString
$cmin :: NixString -> NixString -> NixString
max :: NixString -> NixString -> NixString
$cmax :: NixString -> NixString -> NixString
>= :: NixString -> NixString -> Bool
$c>= :: NixString -> NixString -> Bool
> :: NixString -> NixString -> Bool
$c> :: NixString -> NixString -> Bool
<= :: NixString -> NixString -> Bool
$c<= :: NixString -> NixString -> Bool
< :: NixString -> NixString -> Bool
$c< :: NixString -> NixString -> Bool
compare :: NixString -> NixString -> Ordering
$ccompare :: NixString -> NixString -> Ordering
Ord, Int -> NixString -> ShowS
[NixString] -> ShowS
NixString -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NixString] -> ShowS
$cshowList :: [NixString] -> ShowS
show :: NixString -> String
$cshow :: NixString -> String
showsPrec :: Int -> NixString -> ShowS
$cshowsPrec :: Int -> NixString -> ShowS
Show, forall x. Rep NixString x -> NixString
forall x. NixString -> Rep NixString x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NixString x -> NixString
$cfrom :: forall x. NixString -> Rep NixString x
Generic)

instance Semigroup NixString where
  NixString HashSet StringContext
s1 Text
t1 <> :: NixString -> NixString -> NixString
<> NixString HashSet StringContext
s2 Text
t2 = HashSet StringContext -> Text -> NixString
NixString (HashSet StringContext
s1 forall a. Semigroup a => a -> a -> a
<> HashSet StringContext
s2) (Text
t1 forall a. Semigroup a => a -> a -> a
<> Text
t2)

instance Monoid NixString where
 mempty :: NixString
mempty = HashSet StringContext -> Text -> NixString
NixString forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty

instance Hashable NixString


-- * Functions

-- ** Makers

-- | Constructs NixString without a context
mkNixStringWithoutContext :: Text -> NixString
mkNixStringWithoutContext :: Text -> NixString
mkNixStringWithoutContext = HashSet StringContext -> Text -> NixString
NixString forall a. Monoid a => a
mempty

-- | Create NixString using a singleton context
mkNixStringWithSingletonContext
  :: StringContext -> VarName -> NixString
mkNixStringWithSingletonContext :: StringContext -> VarName -> NixString
mkNixStringWithSingletonContext StringContext
c VarName
s = HashSet StringContext -> Text -> NixString
NixString (forall x. One x => OneItem x -> x
one StringContext
c) (coerce :: forall a b. Coercible a b => a -> b
coerce @VarName @Text VarName
s)

-- | Create NixString from a Text and context
mkNixString
  :: S.HashSet StringContext -> Text -> NixString
mkNixString :: HashSet StringContext -> Text -> NixString
mkNixString = HashSet StringContext -> Text -> NixString
NixString


-- ** Checkers

-- | Returns True if the NixString has an associated context
hasContext :: NixString -> Bool
hasContext :: NixString -> Bool
hasContext (NixString HashSet StringContext
c Text
_) = forall (t :: * -> *) a. Foldable t => t a -> Bool
isPresent HashSet StringContext
c


-- ** Getters

fromNixLikeContext :: NixLikeContext -> S.HashSet StringContext
fromNixLikeContext :: NixLikeContext -> HashSet StringContext
fromNixLikeContext =
  forall a. (Eq a, Hashable a) => [a] -> HashSet a
S.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry VarName -> NixLikeContextValue -> [StringContext]
toStringContexts forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall k v. HashMap k v -> [(k, v)]
M.toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. NixLikeContext -> AttrSet NixLikeContextValue
getNixLikeContext)

-- | Extract the string contents from a NixString that has no context
getStringNoContext :: NixString -> Maybe Text
getStringNoContext :: NixString -> Maybe Text
getStringNoContext (NixString HashSet StringContext
c Text
s)
  | forall (t :: * -> *) a. Foldable t => t a -> Bool
null HashSet StringContext
c    = forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
s
  | Bool
otherwise = forall a. Monoid a => a
mempty

-- | Extract the string contents from a NixString even if the NixString has an associated context
ignoreContext :: NixString -> Text
ignoreContext :: NixString -> Text
ignoreContext (NixString HashSet StringContext
_ Text
s) = Text
s

-- | Get the contents of a 'NixString' and write its context into the resulting set.
extractNixString :: Monad m => NixString -> WithStringContextT m Text
extractNixString :: forall (m :: * -> *).
Monad m =>
NixString -> WithStringContextT m Text
extractNixString (NixString HashSet StringContext
c Text
s) =
  forall (m :: * -> *) a.
WriterT (HashSet StringContext) m a -> WithStringContextT m a
WithStringContextT forall a b. (a -> b) -> a -> b
$
    Text
s forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell HashSet StringContext
c


-- ** Setters

-- this really should be 2 args, then with @toStringContexts path@ laziness it would tail recurse.
-- for now tuple dissected internaly with laziness preservation.
toStringContexts :: VarName -> NixLikeContextValue -> [StringContext]
toStringContexts :: VarName -> NixLikeContextValue -> [StringContext]
toStringContexts VarName
path = NixLikeContextValue -> [StringContext]
go
 where
  go :: NixLikeContextValue -> [StringContext]
  go :: NixLikeContextValue -> [StringContext]
go NixLikeContextValue
cv =
    case NixLikeContextValue
cv of
      NixLikeContextValue Bool
True Bool
_    [Text]
_ ->
        ContextFlavor -> NixLikeContextValue -> [StringContext]
mkLstCtxFor ContextFlavor
DirectPath NixLikeContextValue
cv { nlcvPath :: Bool
nlcvPath = Bool
False }
      NixLikeContextValue Bool
_    Bool
True [Text]
_ ->
        ContextFlavor -> NixLikeContextValue -> [StringContext]
mkLstCtxFor ContextFlavor
AllOutputs NixLikeContextValue
cv { nlcvAllOutputs :: Bool
nlcvAllOutputs = Bool
False }
      NixLikeContextValue Bool
_    Bool
_    [Text]
ls | forall (t :: * -> *) a. Foldable t => t a -> Bool
isPresent [Text]
ls ->
        ContextFlavor -> StringContext
mkCtxFor forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ContextFlavor
DerivationOutput forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
ls
      NixLikeContextValue
_ -> forall a. Monoid a => a
mempty
   where
    mkCtxFor :: ContextFlavor -> StringContext
    mkCtxFor :: ContextFlavor -> StringContext
mkCtxFor ContextFlavor
context = ContextFlavor -> VarName -> StringContext
StringContext ContextFlavor
context VarName
path
    mkLstCtxFor :: ContextFlavor -> NixLikeContextValue -> [StringContext]
    mkLstCtxFor :: ContextFlavor -> NixLikeContextValue -> [StringContext]
mkLstCtxFor ContextFlavor
t NixLikeContextValue
c = forall x. One x => OneItem x -> x
one (ContextFlavor -> StringContext
mkCtxFor ContextFlavor
t) forall a. Semigroup a => a -> a -> a
<> NixLikeContextValue -> [StringContext]
go NixLikeContextValue
c


toNixLikeContextValue :: StringContext -> (NixLikeContextValue, VarName)
toNixLikeContextValue :: StringContext -> (NixLikeContextValue, VarName)
toNixLikeContextValue StringContext
sc =
  ( case StringContext -> ContextFlavor
getStringContextFlavor StringContext
sc of
      ContextFlavor
DirectPath         -> Bool -> Bool -> [Text] -> NixLikeContextValue
NixLikeContextValue Bool
True Bool
False forall a. Monoid a => a
mempty
      ContextFlavor
AllOutputs         -> Bool -> Bool -> [Text] -> NixLikeContextValue
NixLikeContextValue Bool
False Bool
True forall a. Monoid a => a
mempty
      DerivationOutput Text
t -> Bool -> Bool -> [Text] -> NixLikeContextValue
NixLikeContextValue Bool
False Bool
False forall a b. (a -> b) -> a -> b
$ forall x. One x => OneItem x -> x
one Text
t
  , StringContext -> VarName
getStringContextPath StringContext
sc
  )

toNixLikeContext :: S.HashSet StringContext -> NixLikeContext
toNixLikeContext :: HashSet StringContext -> NixLikeContext
toNixLikeContext HashSet StringContext
stringContext =
  AttrSet NixLikeContextValue -> NixLikeContext
NixLikeContext forall a b. (a -> b) -> a -> b
$
    forall b a. (b -> a -> a) -> a -> HashSet b -> a
S.foldr
      StringContext
-> AttrSet NixLikeContextValue -> AttrSet NixLikeContextValue
fun
      forall a. Monoid a => a
mempty
      HashSet StringContext
stringContext
 where
  fun :: (StringContext -> AttrSet NixLikeContextValue -> AttrSet NixLikeContextValue)
  fun :: StringContext
-> AttrSet NixLikeContextValue -> AttrSet NixLikeContextValue
fun StringContext
sc =
    forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
M.insertWith forall a. Semigroup a => a -> a -> a
(<>)) (forall a b. (a, b) -> (b, a)
swap forall a b. (a -> b) -> a -> b
$ StringContext -> (NixLikeContextValue, VarName)
toNixLikeContextValue StringContext
sc)

-- | Add 'StringContext's into the resulting set.
addStringContext
  :: Monad m => S.HashSet StringContext -> WithStringContextT m ()
addStringContext :: forall (m :: * -> *).
Monad m =>
HashSet StringContext -> WithStringContextT m ()
addStringContext = forall (m :: * -> *) a.
WriterT (HashSet StringContext) m a -> WithStringContextT m a
WithStringContextT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell

-- | Add a 'StringContext' into the resulting set.
addSingletonStringContext :: Monad m => StringContext -> WithStringContextT m ()
addSingletonStringContext :: forall (m :: * -> *).
Monad m =>
StringContext -> WithStringContextT m ()
addSingletonStringContext = forall (m :: * -> *) a.
WriterT (HashSet StringContext) m a -> WithStringContextT m a
WithStringContextT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x. One x => OneItem x -> x
one

-- | Run an action producing a string with a context and put those into a 'NixString'.
runWithStringContextT :: Monad m => WithStringContextT m Text -> m NixString
runWithStringContextT :: forall (m :: * -> *).
Monad m =>
WithStringContextT m Text -> m NixString
runWithStringContextT (WithStringContextT WriterT (HashSet StringContext) m Text
m) =
  forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall a b c. (a -> b -> c) -> b -> a -> c
flip HashSet StringContext -> Text -> NixString
NixString) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT WriterT (HashSet StringContext) m Text
m

-- | Run an action producing a string with a context and put those into a 'NixString'.
runWithStringContext :: WithStringContextT Identity Text -> NixString
runWithStringContext :: WithStringContextT Identity Text -> NixString
runWithStringContext = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
Monad m =>
WithStringContextT m Text -> m NixString
runWithStringContextT


-- ** Modifiers

-- | Modify the string part of the NixString, leaving the context unchanged
modifyNixContents :: (Text -> Text) -> NixString -> NixString
modifyNixContents :: (Text -> Text) -> NixString -> NixString
modifyNixContents Text -> Text
f (NixString HashSet StringContext
c Text
s) = HashSet StringContext -> Text -> NixString
NixString HashSet StringContext
c (Text -> Text
f Text
s)

-- | Run an action that manipulates nix strings, and collect the contexts encountered.
-- Warning: this may be unsafe, depending on how you handle the resulting context list.
runWithStringContextT' :: Monad m => WithStringContextT m a -> m (a, S.HashSet StringContext)
runWithStringContextT' :: forall (m :: * -> *) a.
Monad m =>
WithStringContextT m a -> m (a, HashSet StringContext)
runWithStringContextT' (WithStringContextT WriterT (HashSet StringContext) m a
m) = forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT WriterT (HashSet StringContext) m a
m

-- | Run an action that manipulates nix strings, and collect the contexts encountered.
-- Warning: this may be unsafe, depending on how you handle the resulting context list.
runWithStringContext' :: WithStringContextT Identity a -> (a, S.HashSet StringContext)
runWithStringContext' :: forall a.
WithStringContextT Identity a -> (a, HashSet StringContext)
runWithStringContext' = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
Monad m =>
WithStringContextT m a -> m (a, HashSet StringContext)
runWithStringContextT'

-- | Combine NixStrings with a separator
intercalateNixString :: NixString -> [NixString] -> NixString
intercalateNixString :: NixString -> [NixString] -> NixString
intercalateNixString NixString
_   []   = forall a. Monoid a => a
mempty
intercalateNixString NixString
_   [NixString
ns] = NixString
ns
intercalateNixString NixString
sep [NixString]
nss  =
  forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry HashSet StringContext -> Text -> NixString
NixString forall a b. (a -> b) -> a -> b
$
    forall a c b d. (a -> c, b -> d) -> (a, b) -> (c, d)
mapPair
      (forall a. (Eq a, Hashable a) => [HashSet a] -> HashSet a
S.unions forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall x. One x => OneItem x -> x
one (NixString -> HashSet StringContext
getStringContext  NixString
sep) forall a. Semigroup a => a -> a -> a
<>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NixString -> HashSet StringContext
getStringContext forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)
      , Text -> [Text] -> Text
Text.intercalate (NixString -> Text
getStringContent NixString
sep) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NixString -> Text
getStringContent forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>)
      )
      forall a b. (a -> b) -> a -> b
$ forall a. a -> (a, a)
dup [NixString]
nss