{-# LANGUAGE RankNTypes #-} {-# OPTIONS_HADDOCK ignore-exports #-} module XPrelude.Extra ( module Exports, String, Container, unwrapError, dropInitialColons, strictifyEither, scientific2text, text2Scientific, ifromList, ikeys, ifromListWith, iunionWith, iinsertWith, -- * Logger loggerName, logDebug, logDebugStr, logInfo, logInfoStr, logWarning, logWarningStr, logError, logErrorStr, logCritical, logCriticalStr, -- * Lenses for json avalues, nth, ) where import Control.Exception.Lens as Exports (catching) import Control.Lens as Exports hiding ( Strict, argument, noneOf, op, (<.>), ) import Control.Monad as Exports (fail) import Control.Monad.Trans.Except as Exports (except) import Control.Monad.Trans.Maybe as Exports (runMaybeT) import Data.Aeson (Value (..)) import Data.Aeson as Exports (FromJSON, ToJSON, fromJSON, toJSON) import Data.Aeson.Lens as Exports (key, _Array, _Object, _String) import Data.Attoparsec.Text (parseOnly, rational) import qualified Data.Either.Strict as S import Data.HashMap.Strict as Exports (HashMap) import qualified Data.HashMap.Strict as Map import Data.HashSet as Exports (HashSet) import qualified Data.HashSet as HS import Data.Scientific as Exports (Scientific) import qualified Data.Scientific as Scientific import Data.String (String) import Data.String as Exports (IsString (..)) import qualified Data.Text as Text import Data.Tuple.Strict as Exports (Pair (..)) import Data.Vector as Exports (Vector) import Protolude as Exports hiding ( Down, Infix, Prefix, Selector, State, StateT, break, check, evalState, evalStateT, execState, execStateT, from, hash, list, moduleName, runState, runStateT, sourceColumn, sourceLine, to, typeOf, uncons, unsnoc, withState, (%), (<&>), (<.>), ) import qualified System.Log.Logger as Log import Text.Regex.PCRE.ByteString.Utils as Exports (Regex) import XPrelude.PP type Container = Map.HashMap Text text2Scientific :: Text -> Maybe Scientific text2Scientific t = rightToMaybe (parseOnly rational t) scientific2text :: Scientific -> Text scientific2text n = case Scientific.floatingOrInteger n of Left r -> show (r :: Double) Right i -> show (i :: Integer) strictifyEither :: Either a b -> S.Either a b strictifyEither (Left x) = S.Left x strictifyEither (Right x) = S.Right x -- | Helper for hashmap, in case we want another kind of map. ifromList :: (Monoid m, At m, Foldable f) => f (Index m, IxValue m) -> m {-# INLINEABLE ifromList #-} ifromList = foldl' (\curm (k, v) -> curm & at k ?~ v) mempty -- | Return all the keys of a map in a set. ikeys :: (Eq k, Hashable k) => HashMap k v -> HS.HashSet k {-# INLINEABLE ikeys #-} ikeys = HS.fromList . Map.keys ifromListWith :: (Monoid m, At m, Foldable f) => (IxValue m -> IxValue m -> IxValue m) -> f (Index m, IxValue m) -> m {-# INLINEABLE ifromListWith #-} ifromListWith f = foldl' (\curmap (k, v) -> iinsertWith f k v curmap) mempty iinsertWith :: (At m) => (IxValue m -> IxValue m -> IxValue m) -> Index m -> IxValue m -> m -> m {-# INLINEABLE iinsertWith #-} iinsertWith f k v m = m & at k %~ mightreplace where mightreplace Nothing = Just v mightreplace (Just x) = Just (f v x) iunionWith :: (Hashable k, Eq k) => (v -> v -> v) -> HashMap k v -> HashMap k v -> HashMap k v {-# INLINEABLE iunionWith #-} iunionWith = Map.unionWith -- | Remove the '::' token from a text if any. dropInitialColons :: Text -> Text dropInitialColons t = fromMaybe t (Text.stripPrefix "::" t) loggerName :: String loggerName = "language-puppet" logDebug :: Text -> IO () logDebug = Log.debugM "language-puppet" . toS logInfo :: Text -> IO () logInfo = Log.infoM "language-puppet" . toS logInfoStr :: String -> IO () logInfoStr = Log.infoM "language-puppet" logWarning :: Text -> IO () logWarning = Log.warningM "language-puppet" . toS logWarningStr :: String -> IO () logWarningStr = Log.warningM "language-puppet" logError :: Text -> IO () logError = Log.errorM "language-puppet" . toS logErrorStr :: String -> IO () logErrorStr = Log.errorM "language-puppet" logCritical :: Text -> IO () logCritical = Log.criticalM "language-puppet" . toS logCriticalStr :: String -> IO () logCriticalStr = Log.criticalM "language-puppet" logDebugStr :: String -> IO () logDebugStr = Log.debugM "language-puppet" -- | In case of a Left error, print and exit immediately. unwrapError :: Doc -> Either PrettyError a -> IO a unwrapError desc = either exit pure where exit err = putDoc (display err) >> exitFailure display err = red desc <> ":" <+> getError err avalues :: IndexedTraversal' Int Value Value avalues = _Array . traversed nth :: Int -> Traversal' Value Value nth i = _Array . ix i