------------------------------------------------------------------------------
-- |
-- Module      : LiterateX.Types.TargetFormat
-- Description : target format type
-- Copyright   : Copyright (c) 2021-2023 Travis Cardwell
-- License     : MIT
------------------------------------------------------------------------------

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module LiterateX.Types.TargetFormat
  ( -- * Type
    TargetFormat(..)
    -- * API
  , describe
  , list
  , mkEndCode
  , mkBeginCode
  ) where

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

-- https://hackage.haskell.org/package/ttc
import qualified Data.TTC as TTC

-- (literatex)
import LiterateX.Types.CodeLanguage (CodeLanguage)

------------------------------------------------------------------------------
-- $Type

-- | Target format
--
-- This sum type defines the supported target formats.
--
-- Documentation:
--
-- * [Pandoc Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown)
-- * [GitHub Flavored Markdown](https://github.github.com/gfm/)
-- * [mdBook Markdown](https://rust-lang.github.io/mdBook/)
--
-- @since 0.2.1.0
data TargetFormat
  = PandocMarkdown
  | GitHubFlavoredMarkdown
  | MdBook
  deriving (TargetFormat
forall a. a -> a -> Bounded a
maxBound :: TargetFormat
$cmaxBound :: TargetFormat
minBound :: TargetFormat
$cminBound :: TargetFormat
Bounded, Int -> TargetFormat
TargetFormat -> Int
TargetFormat -> [TargetFormat]
TargetFormat -> TargetFormat
TargetFormat -> TargetFormat -> [TargetFormat]
TargetFormat -> TargetFormat -> TargetFormat -> [TargetFormat]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: TargetFormat -> TargetFormat -> TargetFormat -> [TargetFormat]
$cenumFromThenTo :: TargetFormat -> TargetFormat -> TargetFormat -> [TargetFormat]
enumFromTo :: TargetFormat -> TargetFormat -> [TargetFormat]
$cenumFromTo :: TargetFormat -> TargetFormat -> [TargetFormat]
enumFromThen :: TargetFormat -> TargetFormat -> [TargetFormat]
$cenumFromThen :: TargetFormat -> TargetFormat -> [TargetFormat]
enumFrom :: TargetFormat -> [TargetFormat]
$cenumFrom :: TargetFormat -> [TargetFormat]
fromEnum :: TargetFormat -> Int
$cfromEnum :: TargetFormat -> Int
toEnum :: Int -> TargetFormat
$ctoEnum :: Int -> TargetFormat
pred :: TargetFormat -> TargetFormat
$cpred :: TargetFormat -> TargetFormat
succ :: TargetFormat -> TargetFormat
$csucc :: TargetFormat -> TargetFormat
Enum, TargetFormat -> TargetFormat -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TargetFormat -> TargetFormat -> Bool
$c/= :: TargetFormat -> TargetFormat -> Bool
== :: TargetFormat -> TargetFormat -> Bool
$c== :: TargetFormat -> TargetFormat -> Bool
Eq, Eq TargetFormat
TargetFormat -> TargetFormat -> Bool
TargetFormat -> TargetFormat -> Ordering
TargetFormat -> TargetFormat -> TargetFormat
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
min :: TargetFormat -> TargetFormat -> TargetFormat
$cmin :: TargetFormat -> TargetFormat -> TargetFormat
max :: TargetFormat -> TargetFormat -> TargetFormat
$cmax :: TargetFormat -> TargetFormat -> TargetFormat
>= :: TargetFormat -> TargetFormat -> Bool
$c>= :: TargetFormat -> TargetFormat -> Bool
> :: TargetFormat -> TargetFormat -> Bool
$c> :: TargetFormat -> TargetFormat -> Bool
<= :: TargetFormat -> TargetFormat -> Bool
$c<= :: TargetFormat -> TargetFormat -> Bool
< :: TargetFormat -> TargetFormat -> Bool
$c< :: TargetFormat -> TargetFormat -> Bool
compare :: TargetFormat -> TargetFormat -> Ordering
$ccompare :: TargetFormat -> TargetFormat -> Ordering
Ord, Int -> TargetFormat -> ShowS
[TargetFormat] -> ShowS
TargetFormat -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [TargetFormat] -> ShowS
$cshowList :: [TargetFormat] -> ShowS
show :: TargetFormat -> [Char]
$cshow :: TargetFormat -> [Char]
showsPrec :: Int -> TargetFormat -> ShowS
$cshowsPrec :: Int -> TargetFormat -> ShowS
Show)

instance TTC.Parse TargetFormat where
  parse :: forall t e. (Textual t, Textual e) => t -> Either e TargetFormat
parse = forall a t e.
(Bounded a, Enum a, Render a, Textual t, Textual e) =>
[Char] -> Bool -> Bool -> t -> Either e a
TTC.parseEnum' [Char]
"target format" Bool
True Bool
False

instance TTC.Render TargetFormat where
  render :: forall t. Textual t => TargetFormat -> t
render = forall t. Textual t => [Char] -> t
TTC.fromS forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
    TargetFormat
PandocMarkdown         -> [Char]
"pandoc"
    TargetFormat
GitHubFlavoredMarkdown -> [Char]
"github"
    TargetFormat
MdBook                 -> [Char]
"mdbook"

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

-- | Get a description of a target format
--
-- @since 0.0.1.0
describe :: TargetFormat -> String
describe :: TargetFormat -> [Char]
describe = \case
    TargetFormat
PandocMarkdown         -> [Char]
"Pandoc Markdown"
    TargetFormat
GitHubFlavoredMarkdown -> [Char]
"GitHub Flavored Markdown"
    TargetFormat
MdBook                 -> [Char]
"mdBook Markdown"

------------------------------------------------------------------------------

-- | List of all supported target formats
--
-- @since 0.0.1.0
list :: [TargetFormat]
list :: [TargetFormat]
list = [forall a. Bounded a => a
minBound ..]

------------------------------------------------------------------------------

-- | Make line in the target format to end a block of source code
--
-- @since 0.0.1.0
mkEndCode
  :: TargetFormat
  -> Text
mkEndCode :: TargetFormat -> Text
mkEndCode TargetFormat
_anyFormat = Text
"```"

------------------------------------------------------------------------------

-- | Make line in the target format to begin a block of code
--
-- This function is written to indicate how it is used.  Given the target
-- format, optional code language, and line numbering flag, this function
-- returns a function that takes a line number and returns a line.
--
-- The 'MdBook' format does not support per-block line numbering, so the line
-- numbering flag is ignored for that format.
--
-- @since 0.0.1.0
mkBeginCode
  :: TargetFormat
  -> Maybe CodeLanguage
  -> Bool           -- ^ 'True' to number code lines
  -> (Int -> Text)  -- ^ make line for code starting at specified line number
mkBeginCode :: TargetFormat -> Maybe CodeLanguage -> Bool -> Int -> Text
mkBeginCode TargetFormat
PandocMarkdown (Just CodeLanguage
lang) Bool
True = \Int
lineNum -> [Text] -> Text
T.concat
    [ Text
"``` {.", forall a t. (Render a, Textual t) => a -> t
TTC.render CodeLanguage
lang, Text
" .numberSource startFrom=\""
    , forall a t. (Show a, Textual t) => a -> t
TTC.renderWithShow Int
lineNum, Text
"\"}"
    ]
mkBeginCode TargetFormat
PandocMarkdown (Just CodeLanguage
lang) Bool
False = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat
    [ Text
"```", forall a t. (Render a, Textual t) => a -> t
TTC.render CodeLanguage
lang
    ]
mkBeginCode TargetFormat
PandocMarkdown Maybe CodeLanguage
Nothing Bool
True = \Int
lineNum -> [Text] -> Text
T.concat
    [ Text
"``` {.numberSource startFrom=\"", forall a t. (Show a, Textual t) => a -> t
TTC.renderWithShow Int
lineNum, Text
"\"}"
    ]
mkBeginCode TargetFormat
GitHubFlavoredMarkdown (Just CodeLanguage
lang) Bool
True = \Int
lineNum -> [Text] -> Text
T.concat
    [ Text
"``` ", forall a t. (Render a, Textual t) => a -> t
TTC.render CodeLanguage
lang, Text
" startline=", forall a t. (Show a, Textual t) => a -> t
TTC.renderWithShow Int
lineNum
    ]
mkBeginCode TargetFormat
GitHubFlavoredMarkdown (Just CodeLanguage
lang) Bool
False = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat
    [ Text
"``` ", forall a t. (Render a, Textual t) => a -> t
TTC.render CodeLanguage
lang
    ]
mkBeginCode TargetFormat
GitHubFlavoredMarkdown Maybe CodeLanguage
Nothing Bool
True = \Int
lineNum -> [Text] -> Text
T.concat
    [ Text
"``` startline=", forall a t. (Show a, Textual t) => a -> t
TTC.renderWithShow Int
lineNum
    ]
mkBeginCode TargetFormat
MdBook (Just CodeLanguage
lang) Bool
_isNumbered = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat
    [ Text
"```", forall a t. (Render a, Textual t) => a -> t
TTC.render CodeLanguage
lang
    ]
mkBeginCode TargetFormat
_anyFormat Maybe CodeLanguage
Nothing Bool
_isNumbered = forall a b. a -> b -> a
const Text
"```"