------------------------------------------------------------------------------
-- |
-- Module      : LiterateX.Renderer
-- Description : target renderer
-- Copyright   : Copyright (c) 2021 Travis Cardwell
-- License     : MIT
--
-- This module implements the target renderer.
------------------------------------------------------------------------------

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}

module LiterateX.Renderer
  ( -- * Types
    Options(..)
    -- * API
  , defaultOptions
  , defaultOptionsFor
  , render
  ) where

-- https://hackage.haskell.org/package/base
import Control.Monad (replicateM_)

-- https://hackage.haskell.org/package/conduit
import qualified Data.Conduit as C
import Data.Conduit (ConduitT)

-- https://hackage.haskell.org/package/text
import qualified Data.Text as T
import Data.Text (Text)

-- (literatex)
import LiterateX.Types (CodeLanguage, SourceLine, TargetFormat)
import qualified LiterateX.Types.SourceLine as SourceLine
import qualified LiterateX.Types.TargetFormat as TargetFormat

------------------------------------------------------------------------------
-- $Types

-- | Renderer options determine how output is rendered
--
-- @since 0.0.1.0
data Options
  = Options
    { Options -> TargetFormat
targetFormat    :: !TargetFormat
    , Options -> Maybe CodeLanguage
codeLanguage    :: !(Maybe CodeLanguage)
    , Options -> Bool
ignoreShebang   :: !Bool  -- ^ 'True' to ignore shebangs
    , Options -> Bool
renderCode      :: !Bool  -- ^ 'True' to render code
    , Options -> Bool
numberCodeLines :: !Bool  -- ^ 'True' to number code lines
    }
  deriving Int -> Options -> ShowS
[Options] -> ShowS
Options -> String
(Int -> Options -> ShowS)
-> (Options -> String) -> ([Options] -> ShowS) -> Show Options
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Options] -> ShowS
$cshowList :: [Options] -> ShowS
show :: Options -> String
$cshow :: Options -> String
showsPrec :: Int -> Options -> ShowS
$cshowsPrec :: Int -> Options -> ShowS
Show

------------------------------------------------------------------------------
-- $API

-- | Default options
--
-- * @targetFormat@: 'TargetFormat.PandocMarkdown'
-- * @codeLanguage@: 'Nothing'
-- * @ignoreShebang@: 'True'
-- * @renderCode@: 'True'
-- * @numberCodeLines@: 'True'
--
-- @since 0.0.1.0
defaultOptions :: Options
defaultOptions :: Options
defaultOptions = Options :: TargetFormat
-> Maybe CodeLanguage -> Bool -> Bool -> Bool -> Options
Options
    { targetFormat :: TargetFormat
targetFormat    = TargetFormat
TargetFormat.PandocMarkdown
    , codeLanguage :: Maybe CodeLanguage
codeLanguage    = Maybe CodeLanguage
forall a. Maybe a
Nothing
    , ignoreShebang :: Bool
ignoreShebang   = Bool
True
    , renderCode :: Bool
renderCode      = Bool
True
    , numberCodeLines :: Bool
numberCodeLines = Bool
True
    }

-- | Default options for the specified code language
--
-- @since 0.0.1.0
defaultOptionsFor :: CodeLanguage -> Options
defaultOptionsFor :: CodeLanguage -> Options
defaultOptionsFor CodeLanguage
lang = Options
defaultOptions
    { codeLanguage :: Maybe CodeLanguage
codeLanguage = CodeLanguage -> Maybe CodeLanguage
forall a. a -> Maybe a
Just CodeLanguage
lang
    }

-- | Create a "Conduit" transformer that renders using the specified options
--
-- The transformer consumes 'SourceLine' values annotated with the line number
-- and produces lines of output.
--
-- @since 0.0.1.0
render
  :: forall m. Monad m
  => Options
  -> ConduitT (Int, SourceLine) Text m ()
render :: Options -> ConduitT (Int, SourceLine) Text m ()
render Options{Bool
Maybe CodeLanguage
TargetFormat
numberCodeLines :: Bool
renderCode :: Bool
ignoreShebang :: Bool
codeLanguage :: Maybe CodeLanguage
targetFormat :: TargetFormat
numberCodeLines :: Options -> Bool
renderCode :: Options -> Bool
ignoreShebang :: Options -> Bool
codeLanguage :: Options -> Maybe CodeLanguage
targetFormat :: Options -> TargetFormat
..} = ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sStart
  where
    -- Start state
    sStart
      :: Maybe (Int, SourceLine)
      -> ConduitT (Int, SourceLine) Text m ()
    sStart :: Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sStart (Just (Int
lineNum, SourceLine
sourceLine)) = case SourceLine
sourceLine of
      -- render shebang if enabled, otherwise skip
      SourceLine.Shebang Text
line
        | Bool
renderCode Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
ignoreShebang -> do
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Text -> ConduitT (Int, SourceLine) Text m ())
-> Text -> ConduitT (Int, SourceLine) Text m ()
forall a b. (a -> b) -> a -> b
$ Int -> Text
startShebang Int
lineNum
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
endCode
            ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
        | Bool
otherwise -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sStart
      -- start rendering documentation
      SourceLine.Doc Text
line -> do
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sDoc
      -- start rendering code if enabled, otherwise skip
      SourceLine.Code Text
line
        | Bool
renderCode -> do
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Text -> ConduitT (Int, SourceLine) Text m ())
-> Text -> ConduitT (Int, SourceLine) Text m ()
forall a b. (a -> b) -> a -> b
$ Int -> Text
startCode Int
lineNum
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
            ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int
-> Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sCode Int
0
        | Bool
otherwise -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sStart
      -- skip blank lines and rules
      SourceLine
_BlankOrRule -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sStart
    sStart Maybe (Int, SourceLine)
Nothing = () -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

    -- Code state
    sCode
      :: Int  -- ^ number of pending (code) blank lines
      -> Maybe (Int, SourceLine)
      -> ConduitT (Int, SourceLine) Text m ()
    sCode :: Int
-> Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sCode !Int
numBlanks (Just (Int
_lineNum, SourceLine
sourceLine)) = case SourceLine
sourceLine of
      -- render any pending blank lines and code
      SourceLine.Code Text
line -> do
        Int
-> ConduitT (Int, SourceLine) Text m ()
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
numBlanks (ConduitT (Int, SourceLine) Text m ()
 -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
-> ConduitT (Int, SourceLine) Text m ()
forall a b. (a -> b) -> a -> b
$ Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
T.empty
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int
-> Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sCode Int
0
      -- increment number of pending blank lines
      SourceLine
SourceLine.CodeBlank -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int
-> Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sCode (Int
numBlanks Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
      -- end code, add blank line, start rendering documentation
      SourceLine.Doc Text
line -> do
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
endCode
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
T.empty
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sDoc
      -- end code, enter blank state
      SourceLine
SourceLine.DocBlank -> do
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
endCode
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
      -- end code, enter blank state
      SourceLine
SourceLine.Rule -> do
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
endCode
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
      -- shebang only possible on first line (seen in start state)
      SourceLine.Shebang Text
_line -> String -> ConduitT (Int, SourceLine) Text m ()
forall a. HasCallStack => String -> a
error String
"impossible: Shebang in sCode"
    sCode Int
_numBlanks Maybe (Int, SourceLine)
Nothing = Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
endCode

    -- Documentation state
    sDoc
      :: Maybe (Int, SourceLine)
      -> ConduitT (Int, SourceLine) Text m ()
    sDoc :: Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sDoc (Just (Int
lineNum, SourceLine
sourceLine)) = case SourceLine
sourceLine of
      -- render documentation
      SourceLine.Doc Text
line -> do
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sDoc
      -- start rendering code if enabled, otherwise enter blank state
      SourceLine.Code Text
line
        | Bool
renderCode -> do
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
T.empty
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Text -> ConduitT (Int, SourceLine) Text m ())
-> Text -> ConduitT (Int, SourceLine) Text m ()
forall a b. (a -> b) -> a -> b
$ Int -> Text
startCode Int
lineNum
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
            ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int
-> Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sCode Int
0
        | Bool
otherwise -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
      -- shebang only possible on first line (seen in start state)
      SourceLine.Shebang Text
_line -> String -> ConduitT (Int, SourceLine) Text m ()
forall a. HasCallStack => String -> a
error String
"impossible: Shebang in sDoc"
      -- blank lines and rules transition to blank state
      SourceLine
_BlankOrRule -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
    sDoc Maybe (Int, SourceLine)
Nothing = () -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

    -- Blank state
    sBlank
      :: Maybe (Int, SourceLine)
      -> ConduitT (Int, SourceLine) Text m ()
    sBlank :: Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank (Just (Int
lineNum, SourceLine
sourceLine)) = case SourceLine
sourceLine of
      -- start rendering code if enabled, otherwise skip
      SourceLine.Code Text
line
        | Bool
renderCode -> do
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
T.empty
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Text -> ConduitT (Int, SourceLine) Text m ())
-> Text -> ConduitT (Int, SourceLine) Text m ()
forall a b. (a -> b) -> a -> b
$ Int -> Text
startCode Int
lineNum
            Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
            ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int
-> Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sCode Int
0
        | Bool
otherwise -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
      -- render blank line, start rendering documentation
      SourceLine.Doc Text
line -> do
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
T.empty
        Text -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Text
line
        ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sDoc
      -- shebang only possible on first line (seen in start state)
      SourceLine.Shebang Text
_line  -> String -> ConduitT (Int, SourceLine) Text m ()
forall a. HasCallStack => String -> a
error String
"impossible: Shebang in sBlank"
      -- skip additional blank lines and rules
      SourceLine
_BlankOrRule -> ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await ConduitT (Int, SourceLine) Text m (Maybe (Int, SourceLine))
-> (Maybe (Int, SourceLine)
    -> ConduitT (Int, SourceLine) Text m ())
-> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Int, SourceLine) -> ConduitT (Int, SourceLine) Text m ()
sBlank
    sBlank Maybe (Int, SourceLine)
Nothing = () -> ConduitT (Int, SourceLine) Text m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

    -- start code line for code starting at given line number
    startCode :: Int -> Text
    startCode :: Int -> Text
startCode =
      TargetFormat -> Maybe CodeLanguage -> Bool -> Int -> Text
TargetFormat.mkBeginCode TargetFormat
targetFormat Maybe CodeLanguage
codeLanguage Bool
numberCodeLines

    -- shebang start code line does not use syntax highlighting
    startShebang :: Int -> Text
    startShebang :: Int -> Text
startShebang =
      TargetFormat -> Maybe CodeLanguage -> Bool -> Int -> Text
TargetFormat.mkBeginCode TargetFormat
targetFormat Maybe CodeLanguage
forall a. Maybe a
Nothing Bool
numberCodeLines

    -- end code line
    endCode :: Text
    endCode :: Text
endCode = TargetFormat -> Text
TargetFormat.mkEndCode TargetFormat
targetFormat
{-# ANN render ("HLint: ignore Reduce duplication" :: String) #-}