packages feed

mdoc-0.1.0.0: src/Mdoc/Input.hs

-- |
--
-- Module      : Mdoc.Input
-- Copyright   : (c) 2026 Patrick Brisbin
-- License     : AGPL-3
-- Maintainer  : pbrisbin@gmail.com
-- Stability   : experimental
-- Portability : POSIX
module Mdoc.Input
  ( Input (..)
  , Parsed (..)
  , forInputs_
  , parseMdocBytes
  ) where

import Mdoc.Prelude

import Codec.Compression.GZip qualified as GZip
import Data.ByteString.Lazy (LazyByteString)
import Data.ByteString.Lazy qualified as BSL
import Data.Text.Encoding (decodeUtf8With)
import Data.Text.Encoding.Error (lenientDecode)
import Mdoc
import Mdoc.Detect
import Mdoc.Parse
import System.FilePath (takeExtension)

data Input = Input
  { name :: String
  , source :: Text
  , parsed :: Parsed
  }

data Parsed
  = SkipParse Unparsable
  | ParseError ParseError
  | Parsed Mdoc

forInputs_ :: MonadIO m => [FilePath] -> (Input -> m a) -> m ()
forInputs_ inputs f = case inputs of
  [] -> void . f . mkInput "<stdin>" =<< liftIO BSL.getContents
  paths -> for_ paths $ \path -> do
    f . mkInput path =<< liftIO (BSL.readFile path)

mkInput :: String -> LazyByteString -> Input
mkInput name bytes =
  let
    source = decodeUtf8With lenientDecode $ BSL.toStrict bytes
    parsed = either ParseError Parsed $ parseMdocBytes name bytes
    input p = Input {name, source, parsed = p}
  in
    input $ maybe parsed SkipParse $ detectParsable name source

parseMdocBytes
  :: FilePath
  -- ^ Path used for parse errors and detecting gzip
  -> LazyByteString
  -> Either ParseError Mdoc
parseMdocBytes path =
  runParser parseMdoc path
    . decodeUtf8With lenientDecode
    . BSL.toStrict
    . decompress
 where
  decompress
    | takeExtension path == ".gz" = GZip.decompress
    | otherwise = id