Skip to content

How to keeping ExitCodes from folds? #461

@clintonmead

Description

@clintonmead

I wish to "fold" over the lines of a shell command's output, and then make a decision about how to continue based on both the result of the fold AND the exit status.

For example I may be looking for some particular text in the output AND a particular non-zero exit status at the same time. And whilst I'm searching for the text I may want to echo all output (or perhaps some or none) back to the user.

But the issue is the function, inprocWithErr, which is close to what I want, doesn't return the ExitCode, but instead throws it if it is non-zero.

Problem is if it throws, I can catch it but then the result of the fold is gone.

I've hacked up the following, using IORef to hold the fold accumulator so it's not lost on catching an exception, but I feel like it's hacky and I don't like it:

foldInprocWithErr :: MonadIO io => (Either Line Line -> a -> IO a) -> a -> Text -> [Text] -> Shell Line -> io (ExitCode, a)
foldInprocWithErr step initial cmd args stdinLines = liftIO $ do
  accRef <- newIORef initial

  let shellAction = do
        eLine <- T.inprocWithErr cmd args stdinLines
        acc0  <- liftIO (readIORef accRef)
        acc1  <- liftIO (step eLine acc0)
        liftIO (writeIORef accRef acc1)

  result <- try (T.sh shellAction) :: IO (Either ExitCode ())
  acc    <- readIORef accRef
  let exitCode = either id (const ExitSuccess) result
  pure (exitCode, acc)

Is there a better way to approach what I've done above? I considered functions like Turtle.Shell.foldIO but I can't see how that helps because on anything non-zero exit status I'm still going to have to catch an exception, and then I've lost the result, unless I've stashed it away whilst processing in an IORef.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions