{-# LANGUAGE UndecidableInstances #-}

module Shrun.Configuration.Data.Truncation
  ( TruncRegion (..),
    Truncation (..),
    parseTruncation,
    LineTruncation (..),
    parseLineTruncation,

    -- * Misc
    decodeCommandNameTrunc,
    decodeLineTrunc,
    DetectResult (..),
    mergeLineTrunc,
    lineTruncMeta,
  )
where

import Effects.System.Terminal (getTerminalWidth)
import Shrun.Configuration.Data.WithDisabled
  ( WithDisabled
      ( Disabled,
        With
      ),
  )
import Shrun.Prelude
import Shrun.Utils ((∸))
import Shrun.Utils qualified as Utils

-- | The different regions to apply truncation rules.
data TruncRegion
  = -- | Apply truncation rules to commands/key names.
    TruncCommandName
  | -- | Apply truncation rules to command log entire lines.
    TruncLine
  deriving stock (TruncRegion -> TruncRegion -> Bool
(TruncRegion -> TruncRegion -> Bool)
-> (TruncRegion -> TruncRegion -> Bool) -> Eq TruncRegion
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TruncRegion -> TruncRegion -> Bool
== :: TruncRegion -> TruncRegion -> Bool
$c/= :: TruncRegion -> TruncRegion -> Bool
/= :: TruncRegion -> TruncRegion -> Bool
Eq, Int -> TruncRegion -> ShowS
[TruncRegion] -> ShowS
TruncRegion -> String
(Int -> TruncRegion -> ShowS)
-> (TruncRegion -> String)
-> ([TruncRegion] -> ShowS)
-> Show TruncRegion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TruncRegion -> ShowS
showsPrec :: Int -> TruncRegion -> ShowS
$cshow :: TruncRegion -> String
show :: TruncRegion -> String
$cshowList :: [TruncRegion] -> ShowS
showList :: [TruncRegion] -> ShowS
Show)

-- | The maximum number of command characters to display in the logs.
type Truncation :: TruncRegion -> Type
newtype Truncation a = MkTruncation
  { forall (a :: TruncRegion). Truncation a -> Int
unTruncation :: Int
  }
  deriving stock (Truncation a -> Truncation a -> Bool
(Truncation a -> Truncation a -> Bool)
-> (Truncation a -> Truncation a -> Bool) -> Eq (Truncation a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
$c== :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
== :: Truncation a -> Truncation a -> Bool
$c/= :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
/= :: Truncation a -> Truncation a -> Bool
Eq, Eq (Truncation a)
Eq (Truncation a) =>
(Truncation a -> Truncation a -> Ordering)
-> (Truncation a -> Truncation a -> Bool)
-> (Truncation a -> Truncation a -> Bool)
-> (Truncation a -> Truncation a -> Bool)
-> (Truncation a -> Truncation a -> Bool)
-> (Truncation a -> Truncation a -> Truncation a)
-> (Truncation a -> Truncation a -> Truncation a)
-> Ord (Truncation a)
Truncation a -> Truncation a -> Bool
Truncation a -> Truncation a -> Ordering
Truncation a -> Truncation a -> Truncation a
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
forall (a :: TruncRegion). Eq (Truncation a)
forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
forall (a :: TruncRegion). Truncation a -> Truncation a -> Ordering
forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
$ccompare :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Ordering
compare :: Truncation a -> Truncation a -> Ordering
$c< :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
< :: Truncation a -> Truncation a -> Bool
$c<= :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
<= :: Truncation a -> Truncation a -> Bool
$c> :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
> :: Truncation a -> Truncation a -> Bool
$c>= :: forall (a :: TruncRegion). Truncation a -> Truncation a -> Bool
>= :: Truncation a -> Truncation a -> Bool
$cmax :: forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
max :: Truncation a -> Truncation a -> Truncation a
$cmin :: forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
min :: Truncation a -> Truncation a -> Truncation a
Ord, Int -> Truncation a -> ShowS
[Truncation a] -> ShowS
Truncation a -> String
(Int -> Truncation a -> ShowS)
-> (Truncation a -> String)
-> ([Truncation a] -> ShowS)
-> Show (Truncation a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (a :: TruncRegion). Int -> Truncation a -> ShowS
forall (a :: TruncRegion). [Truncation a] -> ShowS
forall (a :: TruncRegion). Truncation a -> String
$cshowsPrec :: forall (a :: TruncRegion). Int -> Truncation a -> ShowS
showsPrec :: Int -> Truncation a -> ShowS
$cshow :: forall (a :: TruncRegion). Truncation a -> String
show :: Truncation a -> String
$cshowList :: forall (a :: TruncRegion). [Truncation a] -> ShowS
showList :: [Truncation a] -> ShowS
Show)
  deriving (Integer -> Truncation a
Truncation a -> Truncation a
Truncation a -> Truncation a -> Truncation a
(Truncation a -> Truncation a -> Truncation a)
-> (Truncation a -> Truncation a -> Truncation a)
-> (Truncation a -> Truncation a -> Truncation a)
-> (Truncation a -> Truncation a)
-> (Truncation a -> Truncation a)
-> (Truncation a -> Truncation a)
-> (Integer -> Truncation a)
-> Num (Truncation a)
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
forall (a :: TruncRegion). Integer -> Truncation a
forall (a :: TruncRegion). Truncation a -> Truncation a
forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
$c+ :: forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
+ :: Truncation a -> Truncation a -> Truncation a
$c- :: forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
- :: Truncation a -> Truncation a -> Truncation a
$c* :: forall (a :: TruncRegion).
Truncation a -> Truncation a -> Truncation a
* :: Truncation a -> Truncation a -> Truncation a
$cnegate :: forall (a :: TruncRegion). Truncation a -> Truncation a
negate :: Truncation a -> Truncation a
$cabs :: forall (a :: TruncRegion). Truncation a -> Truncation a
abs :: Truncation a -> Truncation a
$csignum :: forall (a :: TruncRegion). Truncation a -> Truncation a
signum :: Truncation a -> Truncation a
$cfromInteger :: forall (a :: TruncRegion). Integer -> Truncation a
fromInteger :: Integer -> Truncation a
Num, (forall ann. Truncation a -> Doc ann)
-> (forall ann. [Truncation a] -> Doc ann) -> Pretty (Truncation a)
forall ann. [Truncation a] -> Doc ann
forall ann. Truncation a -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
forall (a :: TruncRegion) ann. [Truncation a] -> Doc ann
forall (a :: TruncRegion) ann. Truncation a -> Doc ann
$cpretty :: forall (a :: TruncRegion) ann. Truncation a -> Doc ann
pretty :: forall ann. Truncation a -> Doc ann
$cprettyList :: forall (a :: TruncRegion) ann. [Truncation a] -> Doc ann
prettyList :: forall ann. [Truncation a] -> Doc ann
Pretty) via Int

instance
  (k ~ An_Iso, a ~ Int, b ~ Int) =>
  LabelOptic "unTruncation" k (Truncation r) (Truncation r) a b
  where
  labelOptic :: Optic k NoIx (Truncation r) (Truncation r) a b
labelOptic = (Truncation r -> a)
-> (b -> Truncation r) -> Iso (Truncation r) (Truncation r) a b
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso (\(MkTruncation Int
x) -> a
Int
x) b -> Truncation r
Int -> Truncation r
forall (a :: TruncRegion). Int -> Truncation a
MkTruncation
  {-# INLINE labelOptic #-}

instance DecodeTOML (Truncation a) where
  tomlDecoder :: Decoder (Truncation a)
tomlDecoder = Decoder Natural -> Decoder (Truncation a)
forall (m :: Type -> Type) (r :: TruncRegion).
MonadFail m =>
m Natural -> m (Truncation r)
parseTruncation Decoder Natural
forall a. DecodeTOML a => Decoder a
tomlDecoder

parseTruncation :: (MonadFail m) => m Natural -> m (Truncation r)
parseTruncation :: forall (m :: Type -> Type) (r :: TruncRegion).
MonadFail m =>
m Natural -> m (Truncation r)
parseTruncation m Natural
getNat = do
  Natural
n <- m Natural
getNat
  case Natural -> Either String Int
forall a b.
(Bits a, Bits b, Integral a, Integral b, Show a, Typeable a,
 Typeable b) =>
a -> Either String b
convertIntegral Natural
n of
    Left String
err -> String -> m (Truncation r)
forall a. String -> m a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail String
err
    Right Int
x -> Truncation r -> m (Truncation r)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Truncation r -> m (Truncation r))
-> Truncation r -> m (Truncation r)
forall a b. (a -> b) -> a -> b
$ Int -> Truncation r
forall (a :: TruncRegion). Int -> Truncation a
MkTruncation Int
x
{-# INLINEABLE parseTruncation #-}

-- | Determines command log line truncation behavior. We need a separate
-- type from 'Truncation' to add a third option, to detect the terminal size
-- automatically.
data LineTruncation
  = Undetected (Truncation TruncLine)
  | Detected
  deriving stock (LineTruncation -> LineTruncation -> Bool
(LineTruncation -> LineTruncation -> Bool)
-> (LineTruncation -> LineTruncation -> Bool) -> Eq LineTruncation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LineTruncation -> LineTruncation -> Bool
== :: LineTruncation -> LineTruncation -> Bool
$c/= :: LineTruncation -> LineTruncation -> Bool
/= :: LineTruncation -> LineTruncation -> Bool
Eq, Int -> LineTruncation -> ShowS
[LineTruncation] -> ShowS
LineTruncation -> String
(Int -> LineTruncation -> ShowS)
-> (LineTruncation -> String)
-> ([LineTruncation] -> ShowS)
-> Show LineTruncation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LineTruncation -> ShowS
showsPrec :: Int -> LineTruncation -> ShowS
$cshow :: LineTruncation -> String
show :: LineTruncation -> String
$cshowList :: [LineTruncation] -> ShowS
showList :: [LineTruncation] -> ShowS
Show)

instance DecodeTOML LineTruncation where
  tomlDecoder :: Decoder LineTruncation
tomlDecoder = Decoder Natural -> Decoder Text -> Decoder LineTruncation
forall (m :: Type -> Type).
(Alternative m, MonadFail m) =>
m Natural -> m Text -> m LineTruncation
parseLineTruncation Decoder Natural
forall a. DecodeTOML a => Decoder a
tomlDecoder Decoder Text
forall a. DecodeTOML a => Decoder a
tomlDecoder

parseLineTruncation ::
  (Alternative m, MonadFail m) =>
  m Natural ->
  m Text ->
  m LineTruncation
parseLineTruncation :: forall (m :: Type -> Type).
(Alternative m, MonadFail m) =>
m Natural -> m Text -> m LineTruncation
parseLineTruncation m Natural
getNat m Text
getTxt =
  Truncation 'TruncLine -> LineTruncation
Undetected
    (Truncation 'TruncLine -> LineTruncation)
-> m (Truncation 'TruncLine) -> m LineTruncation
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> m Natural -> m (Truncation 'TruncLine)
forall (m :: Type -> Type) (r :: TruncRegion).
MonadFail m =>
m Natural -> m (Truncation r)
parseTruncation m Natural
getNat
    -- NOTE: [Detect second parser]
    m LineTruncation -> m LineTruncation -> m LineTruncation
forall a. m a -> m a -> m a
forall (f :: Type -> Type) a. Alternative f => f a -> f a -> f a
<|> m Text -> m LineTruncation
forall (m :: Type -> Type).
MonadFail m =>
m Text -> m LineTruncation
parseDetected m Text
getTxt
{-# INLINEABLE parseLineTruncation #-}

-- Because this parser is used second, its error message is what will be
-- displayed.
--
-- see NOTE: [Detect second parser]
parseDetected :: (MonadFail m) => m Text -> m LineTruncation
parseDetected :: forall (m :: Type -> Type).
MonadFail m =>
m Text -> m LineTruncation
parseDetected m Text
getTxt =
  m Text
getTxt m Text -> (Text -> m LineTruncation) -> m LineTruncation
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Text
"detect" -> LineTruncation -> m LineTruncation
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure LineTruncation
Detected
    Text
bad ->
      String -> m LineTruncation
forall a. String -> m a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail
        (String -> m LineTruncation) -> String -> m LineTruncation
forall a b. (a -> b) -> a -> b
$ String -> (Bool, [String]) -> ShowS
forall a. (IsString a, Monoid a) => a -> (Bool, [a]) -> a -> a
Utils.fmtUnrecognizedError
          String
"line truncation"
          (Bool, [String])
forall a. IsString a => (Bool, [a])
lineTruncMeta
          (Text -> String
unpack Text
bad)
{-# INLINEABLE parseDetected #-}

lineTruncMeta :: (IsString a) => Tuple2 Bool (List a)
lineTruncMeta :: forall a. IsString a => (Bool, [a])
lineTruncMeta = (Bool
True, [a
"NATURAL", a
"detect"])

decodeCommandNameTrunc :: Decoder (Maybe (WithDisabled (Truncation TruncCommandName)))
decodeCommandNameTrunc :: Decoder (Maybe (WithDisabled (Truncation 'TruncCommandName)))
decodeCommandNameTrunc = Decoder (WithDisabled (Truncation 'TruncCommandName))
-> Text
-> Decoder (Maybe (WithDisabled (Truncation 'TruncCommandName)))
forall a. Decoder a -> Text -> Decoder (Maybe a)
getFieldOptWith Decoder (WithDisabled (Truncation 'TruncCommandName))
forall a. DecodeTOML a => Decoder a
tomlDecoder Text
"command-name-trunc"

decodeLineTrunc :: Decoder (Maybe (WithDisabled LineTruncation))
decodeLineTrunc :: Decoder (Maybe (WithDisabled LineTruncation))
decodeLineTrunc = Decoder (WithDisabled LineTruncation)
-> Text -> Decoder (Maybe (WithDisabled LineTruncation))
forall a. Decoder a -> Text -> Decoder (Maybe a)
getFieldOptWith Decoder (WithDisabled LineTruncation)
forall a. DecodeTOML a => Decoder a
tomlDecoder Text
"line-trunc"

-- | Terminal width detect result. We save this so we only look it up at
-- most once (i.e. both --console-log-line-trunc and --file-log-line-trunc
-- are on).
data DetectResult
  = DetectNotRun
  | DetectFailed
  | DetectSucceeded Int

-- | Merges line truncation.
mergeLineTrunc ::
  ( HasCallStack,
    MonadCatch m,
    MonadIORef m,
    MonadTerminal m
  ) =>
  -- | If true, defaults to 'detect'.
  Bool ->
  -- | Detect result cache, so we only look it up at most once.
  IORef DetectResult ->
  -- | Args config.
  Maybe (WithDisabled LineTruncation) ->
  -- | Toml config.
  Maybe (WithDisabled LineTruncation) ->
  m (Maybe (Truncation TruncLine))
mergeLineTrunc :: forall (m :: Type -> Type).
(HasCallStack, MonadCatch m, MonadIORef m, MonadTerminal m) =>
Bool
-> IORef DetectResult
-> Maybe (WithDisabled LineTruncation)
-> Maybe (WithDisabled LineTruncation)
-> m (Maybe (Truncation 'TruncLine))
mergeLineTrunc Bool
defaultDetect IORef DetectResult
detectRef Maybe (WithDisabled LineTruncation)
args Maybe (WithDisabled LineTruncation)
toml = case Maybe (WithDisabled LineTruncation)
args Maybe (WithDisabled LineTruncation)
-> Maybe (WithDisabled LineTruncation)
-> Maybe (WithDisabled LineTruncation)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: Type -> Type) a. Alternative f => f a -> f a -> f a
<|> Maybe (WithDisabled LineTruncation)
toml of
  Maybe (WithDisabled LineTruncation)
Nothing ->
    if Bool
defaultDetect
      then IORef DetectResult
-> Maybe LineTruncation -> m (Maybe (Truncation 'TruncLine))
forall (m :: Type -> Type).
(HasCallStack, MonadCatch m, MonadIORef m, MonadTerminal m) =>
IORef DetectResult
-> Maybe LineTruncation -> m (Maybe (Truncation 'TruncLine))
configToLineTrunc IORef DetectResult
detectRef (LineTruncation -> Maybe LineTruncation
forall a. a -> Maybe a
Just LineTruncation
Detected)
      else Maybe (Truncation 'TruncLine) -> m (Maybe (Truncation 'TruncLine))
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Maybe (Truncation 'TruncLine)
forall a. Maybe a
Nothing
  Just WithDisabled LineTruncation
Disabled -> Maybe (Truncation 'TruncLine) -> m (Maybe (Truncation 'TruncLine))
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Maybe (Truncation 'TruncLine)
forall a. Maybe a
Nothing
  (Just (With LineTruncation
t)) -> IORef DetectResult
-> Maybe LineTruncation -> m (Maybe (Truncation 'TruncLine))
forall (m :: Type -> Type).
(HasCallStack, MonadCatch m, MonadIORef m, MonadTerminal m) =>
IORef DetectResult
-> Maybe LineTruncation -> m (Maybe (Truncation 'TruncLine))
configToLineTrunc IORef DetectResult
detectRef (LineTruncation -> Maybe LineTruncation
forall a. a -> Maybe a
Just LineTruncation
t)

-- | Maps line trunc config to actual value.
configToLineTrunc ::
  ( HasCallStack,
    MonadCatch m,
    MonadIORef m,
    MonadTerminal m
  ) =>
  IORef DetectResult ->
  Maybe LineTruncation ->
  m (Maybe (Truncation TruncLine))
configToLineTrunc :: forall (m :: Type -> Type).
(HasCallStack, MonadCatch m, MonadIORef m, MonadTerminal m) =>
IORef DetectResult
-> Maybe LineTruncation -> m (Maybe (Truncation 'TruncLine))
configToLineTrunc IORef DetectResult
_ Maybe LineTruncation
Nothing = Maybe (Truncation 'TruncLine) -> m (Maybe (Truncation 'TruncLine))
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Maybe (Truncation 'TruncLine)
forall a. Maybe a
Nothing
configToLineTrunc IORef DetectResult
detectRef (Just LineTruncation
Detected) = do
  -- ref exists so that we only check this once, even if both console
  -- and file specify detect.
  Int
width <-
    IORef DetectResult -> m DetectResult
forall a. HasCallStack => IORef a -> m a
forall (m :: Type -> Type) a.
(MonadIORef m, HasCallStack) =>
IORef a -> m a
readIORef' IORef DetectResult
detectRef m DetectResult -> (DetectResult -> m Int) -> m Int
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      DetectSucceeded Int
w -> Int -> m Int
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Int
w
      DetectResult
DetectFailed -> Int -> m Int
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Int
defLen
      DetectResult
DetectNotRun -> do
        -- We subtract one because otherwise we can fill the entire terminal with a
        -- log, which will automatically add a newline. The point of this option is
        -- to avoid multiple lines, hence the subtraction.
        m Int -> m (Either SomeException Int)
forall (m :: Type -> Type) a.
(HasCallStack, MonadCatch m) =>
m a -> m (Either SomeException a)
tryMySync m Int
forall a (m :: Type -> Type).
(HasCallStack, Integral a, MonadTerminal m) =>
m a
getTerminalWidth m (Either SomeException Int)
-> (Either SomeException Int -> m Int) -> m Int
forall a b. m a -> (a -> m b) -> m b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Left SomeException
ex -> do
            let msg :: Text
msg =
                  [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
                    [ Text
"Failed detecting terminal width, defaulting to 80: ",
                      SomeException -> Text
forall e. Exception e => e -> Text
displayExceptiont SomeException
ex
                    ]
            Text -> m ()
forall (m :: Type -> Type).
(HasCallStack, MonadTerminal m) =>
Text -> m ()
putTextLn Text
msg
            IORef DetectResult -> DetectResult -> m ()
forall a. HasCallStack => IORef a -> a -> m ()
forall (m :: Type -> Type) a.
(MonadIORef m, HasCallStack) =>
IORef a -> a -> m ()
writeIORef' IORef DetectResult
detectRef DetectResult
DetectFailed
            pure Int
defLen
          Right Int
w -> do
            let w' :: Int
w' = Int
w Int -> Int -> Int
forall a. (Ord a, Num a) => a -> a -> a
 Int
1
            IORef DetectResult -> DetectResult -> m ()
forall a. HasCallStack => IORef a -> a -> m ()
forall (m :: Type -> Type) a.
(MonadIORef m, HasCallStack) =>
IORef a -> a -> m ()
writeIORef' IORef DetectResult
detectRef (Int -> DetectResult
DetectSucceeded Int
w') m () -> Int -> m Int
forall (f :: Type -> Type) a b. Functor f => f a -> b -> f b
$> Int
w'

  pure $ Truncation 'TruncLine -> Maybe (Truncation 'TruncLine)
forall a. a -> Maybe a
Just (Truncation 'TruncLine -> Maybe (Truncation 'TruncLine))
-> Truncation 'TruncLine -> Maybe (Truncation 'TruncLine)
forall a b. (a -> b) -> a -> b
$ Int -> Truncation 'TruncLine
forall (a :: TruncRegion). Int -> Truncation a
MkTruncation Int
width
  where
    defLen :: Int
defLen = Int
80
configToLineTrunc IORef DetectResult
_ (Just (Undetected Truncation 'TruncLine
x)) = Maybe (Truncation 'TruncLine) -> m (Maybe (Truncation 'TruncLine))
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Maybe (Truncation 'TruncLine)
 -> m (Maybe (Truncation 'TruncLine)))
-> Maybe (Truncation 'TruncLine)
-> m (Maybe (Truncation 'TruncLine))
forall a b. (a -> b) -> a -> b
$ Truncation 'TruncLine -> Maybe (Truncation 'TruncLine)
forall a. a -> Maybe a
Just Truncation 'TruncLine
x
{-# INLINEABLE configToLineTrunc #-}