hnix/src/Nix/String.hs

184 lines
6.8 KiB
Haskell
Raw Normal View History

2018-05-13 20:13:30 +02:00
{-# LANGUAGE DeriveGeneric #-}
2018-12-07 00:02:59 +01:00
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2018-11-17 22:08:02 +01:00
{-# LANGUAGE OverloadedStrings #-}
2018-09-16 22:30:24 +02:00
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
module Nix.String
( NixString
2018-11-21 07:21:53 +01:00
, principledGetContext
, principledMakeNixString
2018-11-17 22:08:02 +01:00
, principledMempty
, StringContext(..)
, ContextFlavor(..)
, stringHasContext
2018-11-17 22:08:02 +01:00
, principledIntercalateNixString
, hackyGetStringNoContext
, principledGetStringNoContext
2018-11-17 20:56:59 +01:00
, principledStringIgnoreContext
, hackyStringIgnoreContext
, hackyMakeNixStringWithoutContext
2018-11-17 22:08:02 +01:00
, principledMakeNixStringWithoutContext
, principledMakeNixStringWithSingletonContext
2018-11-17 22:23:41 +01:00
, principledModifyNixContents
2018-11-17 19:29:34 +01:00
, principledStringMappend
2018-11-17 22:45:11 +01:00
, principledStringMempty
, principledStringMConcat
2018-12-07 00:02:59 +01:00
, WithStringContext
2019-03-16 21:16:45 +01:00
, WithStringContextT(..)
2018-12-07 00:02:59 +01:00
, extractNixString
, addStringContext
, addSingletonStringContext
, runWithStringContextT
2018-12-07 00:02:59 +01:00
, runWithStringContext
)
where
2018-05-13 20:13:30 +02:00
2018-12-07 00:02:59 +01:00
import Control.Monad.Writer
import Data.Functor.Identity
import qualified Data.HashSet as S
2018-05-13 20:13:30 +02:00
import Data.Hashable
import Data.Text ( Text )
import qualified Data.Text as Text
2018-05-13 20:13:30 +02:00
import GHC.Generics
-- {-# WARNING hackyGetStringNoContext, hackyStringIgnoreContext, hackyMakeNixStringWithoutContext "This NixString function needs to be replaced" #-}
2018-05-13 20:13:30 +02:00
-- | A 'ContextFlavor' describes the sum of possible derivations for string contexts
2018-11-17 22:08:02 +01:00
data ContextFlavor =
2018-05-13 20:13:30 +02:00
DirectPath
| DerivationOutput !Text
deriving (Show, Eq, Ord, Generic)
instance Hashable ContextFlavor
-- | A 'StringContext' ...
2018-11-17 22:08:02 +01:00
data StringContext =
2018-05-13 20:13:30 +02:00
StringContext { scPath :: !Text
, scFlavor :: !ContextFlavor
2018-11-17 22:08:02 +01:00
} deriving (Eq, Ord, Show, Generic)
2018-05-13 20:13:30 +02:00
instance Hashable StringContext
2018-11-17 22:08:02 +01:00
data NixString = NixString
2018-05-13 20:13:30 +02:00
{ nsContents :: !Text
, nsContext :: !(S.HashSet StringContext)
2018-11-17 22:08:02 +01:00
} deriving (Eq, Ord, Show, Generic)
2018-05-13 20:13:30 +02:00
instance Hashable NixString
2018-11-21 07:21:53 +01:00
principledGetContext :: NixString -> S.HashSet StringContext
principledGetContext = nsContext
2018-11-17 22:08:02 +01:00
-- | Combine two NixStrings using mappend
principledMempty :: NixString
principledMempty = NixString "" mempty
2018-11-17 19:04:08 +01:00
-- | Combine two NixStrings using mappend
principledStringMappend :: NixString -> NixString -> NixString
principledStringMappend (NixString s1 t1) (NixString s2 t2) =
NixString (s1 <> s2) (t1 <> t2)
2018-11-17 19:04:08 +01:00
-- | Combine two NixStrings using mappend
hackyStringMappend :: NixString -> NixString -> NixString
hackyStringMappend (NixString s1 t1) (NixString s2 t2) =
NixString (s1 <> s2) (t1 <> t2)
2018-05-13 20:13:30 +02:00
2018-11-17 22:08:02 +01:00
-- | Combine NixStrings with a separator
principledIntercalateNixString :: NixString -> [NixString] -> NixString
principledIntercalateNixString _ [] = principledMempty
principledIntercalateNixString _ [ns] = ns
principledIntercalateNixString sep nss = NixString contents ctx
where
contents = Text.intercalate (nsContents sep) (map nsContents nss)
ctx = S.unions (nsContext sep : map nsContext nss)
2018-11-17 22:08:02 +01:00
-- | Combine NixStrings using mconcat
hackyStringMConcat :: [NixString] -> NixString
2018-11-17 22:08:02 +01:00
hackyStringMConcat = foldr hackyStringMappend (NixString mempty mempty)
2018-11-17 22:45:11 +01:00
-- | Empty string with empty context.
principledStringMempty :: NixString
principledStringMempty = NixString mempty mempty
-- | Combine NixStrings using mconcat
principledStringMConcat :: [NixString] -> NixString
principledStringMConcat =
foldr principledStringMappend (NixString mempty mempty)
--instance Semigroup NixString where
--NixString s1 t1 <> NixString s2 t2 = NixString (s1 <> s2) (t1 <> t2)
--instance Monoid NixString where
-- mempty = NixString mempty mempty
-- mappend = (<>)
2018-05-13 20:13:30 +02:00
2018-11-17 22:08:02 +01:00
-- | Extract the string contents from a NixString that has no context
hackyGetStringNoContext :: NixString -> Maybe Text
hackyGetStringNoContext (NixString s c) | null c = Just s
| otherwise = Nothing
2018-05-13 20:13:30 +02:00
2018-11-17 23:09:26 +01:00
-- | Extract the string contents from a NixString that has no context
principledGetStringNoContext :: NixString -> Maybe Text
principledGetStringNoContext (NixString s c) | null c = Just s
| otherwise = Nothing
2018-11-17 23:09:26 +01:00
2018-11-17 22:08:02 +01:00
-- | Extract the string contents from a NixString even if the NixString has an associated context
2018-11-17 20:56:59 +01:00
principledStringIgnoreContext :: NixString -> Text
principledStringIgnoreContext (NixString s _) = s
-- | Extract the string contents from a NixString even if the NixString has an associated context
hackyStringIgnoreContext :: NixString -> Text
hackyStringIgnoreContext (NixString s _) = s
2018-05-13 20:13:30 +02:00
-- | Returns True if the NixString has an associated context
stringHasContext :: NixString -> Bool
stringHasContext (NixString _ c) = not (null c)
2018-05-13 20:13:30 +02:00
-- | Constructs a NixString without a context
hackyMakeNixStringWithoutContext :: Text -> NixString
2018-11-17 22:08:02 +01:00
hackyMakeNixStringWithoutContext = flip NixString mempty
-- | Constructs a NixString without a context
principledMakeNixStringWithoutContext :: Text -> NixString
principledMakeNixStringWithoutContext = flip NixString mempty
2018-05-13 20:13:30 +02:00
-- | Modify the string part of the NixString, leaving the context unchanged
2018-11-17 22:23:41 +01:00
principledModifyNixContents :: (Text -> Text) -> NixString -> NixString
principledModifyNixContents f (NixString s c) = NixString (f s) c
2018-05-13 20:13:30 +02:00
2018-11-17 22:08:02 +01:00
-- | Create a NixString using a singleton context
principledMakeNixStringWithSingletonContext
:: Text -> StringContext -> NixString
2018-11-17 22:08:02 +01:00
principledMakeNixStringWithSingletonContext s c = NixString s (S.singleton c)
2018-12-07 00:02:59 +01:00
2018-11-24 21:22:02 +01:00
-- | Create a NixString from a Text and context
2018-11-21 07:21:53 +01:00
principledMakeNixString :: Text -> S.HashSet StringContext -> NixString
principledMakeNixString s c = NixString s c
2018-12-07 00:02:59 +01:00
-- | A monad for accumulating string context while producing a result string.
newtype WithStringContextT m a = WithStringContextT (WriterT (S.HashSet StringContext) m a)
deriving (Functor, Applicative, Monad, MonadTrans, MonadWriter (S.HashSet StringContext))
type WithStringContext = WithStringContextT Identity
-- | Add 'StringContext's into the resulting set.
addStringContext
:: Monad m => S.HashSet StringContext -> WithStringContextT m ()
addStringContext = WithStringContextT . tell
-- | Add a 'StringContext' into the resulting set.
addSingletonStringContext :: Monad m => StringContext -> WithStringContextT m ()
addSingletonStringContext = WithStringContextT . tell . S.singleton
2018-12-07 00:02:59 +01:00
-- | Get the contents of a 'NixString' and write its context into the resulting set.
extractNixString :: Monad m => NixString -> WithStringContextT m Text
extractNixString (NixString s c) = WithStringContextT $ tell c >> return s
-- | Run an action producing a string with a context and put those into a 'NixString'.
runWithStringContextT :: Monad m => WithStringContextT m Text -> m NixString
runWithStringContextT (WithStringContextT m) =
uncurry NixString <$> runWriterT m
2018-12-07 00:02:59 +01:00
-- | Run an action producing a string with a context and put those into a 'NixString'.
runWithStringContext :: WithStringContextT Identity Text -> NixString
runWithStringContext = runIdentity . runWithStringContextT