------------------------------------------------------------------------------
-- |
-- Module      : LiterateX.Types.CodeLanguage
-- Description : source code language type
-- Copyright   : Copyright (c) 2021-2023 Travis Cardwell
-- License     : MIT
------------------------------------------------------------------------------

module LiterateX.Types.CodeLanguage
  ( -- * Type
    CodeLanguage
  ) where

-- https://hackage.haskell.org/package/base
import Control.Monad (when)
import Data.Bifunctor (first)
import Data.Char (isSpace)
import Data.String (IsString(fromString))

-- 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

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

-- | Source code language
--
-- This string is used for syntax highlighting of source code.
--
-- When using Pandoc Markdown, run the following command to see a list of
-- supported languages:
--
-- @
-- \$ pandoc --list-highlight-languages
-- @
--
-- When using GitHub Flavored Markdown, check the following file for supported
-- languages:
--
-- <https://github.com/github/linguist/blob/master/lib/linguist/languages.yml>
--
-- @since 0.0.1.0
newtype CodeLanguage = CodeLanguage { CodeLanguage -> Text
unCodeLanguage :: Text }
  deriving (CodeLanguage -> CodeLanguage -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CodeLanguage -> CodeLanguage -> Bool
$c/= :: CodeLanguage -> CodeLanguage -> Bool
== :: CodeLanguage -> CodeLanguage -> Bool
$c== :: CodeLanguage -> CodeLanguage -> Bool
Eq, Eq CodeLanguage
CodeLanguage -> CodeLanguage -> Bool
CodeLanguage -> CodeLanguage -> Ordering
CodeLanguage -> CodeLanguage -> CodeLanguage
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 :: CodeLanguage -> CodeLanguage -> CodeLanguage
$cmin :: CodeLanguage -> CodeLanguage -> CodeLanguage
max :: CodeLanguage -> CodeLanguage -> CodeLanguage
$cmax :: CodeLanguage -> CodeLanguage -> CodeLanguage
>= :: CodeLanguage -> CodeLanguage -> Bool
$c>= :: CodeLanguage -> CodeLanguage -> Bool
> :: CodeLanguage -> CodeLanguage -> Bool
$c> :: CodeLanguage -> CodeLanguage -> Bool
<= :: CodeLanguage -> CodeLanguage -> Bool
$c<= :: CodeLanguage -> CodeLanguage -> Bool
< :: CodeLanguage -> CodeLanguage -> Bool
$c< :: CodeLanguage -> CodeLanguage -> Bool
compare :: CodeLanguage -> CodeLanguage -> Ordering
$ccompare :: CodeLanguage -> CodeLanguage -> Ordering
Ord, Int -> CodeLanguage -> ShowS
[CodeLanguage] -> ShowS
CodeLanguage -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CodeLanguage] -> ShowS
$cshowList :: [CodeLanguage] -> ShowS
show :: CodeLanguage -> String
$cshow :: CodeLanguage -> String
showsPrec :: Int -> CodeLanguage -> ShowS
$cshowsPrec :: Int -> CodeLanguage -> ShowS
Show)

instance IsString CodeLanguage where
  fromString :: String -> CodeLanguage
fromString = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. HasCallStack => String -> a
error forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a t e. (Parse a, Textual t, Textual e) => t -> Either e a
TTC.parse

instance TTC.Parse CodeLanguage where
  parse :: forall t e. (Textual t, Textual e) => t -> Either e CodeLanguage
parse = forall t a. Textual t => (Text -> a) -> t -> a
TTC.asT forall a b. (a -> b) -> a -> b
$ \Text
t -> forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first forall t. Textual t => String -> t
TTC.fromS forall a b. (a -> b) -> a -> b
$ do
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text -> Bool
T.null Text
t) forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left String
"invalid code language: empty"
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((Char -> Bool) -> Text -> Bool
T.any Char -> Bool
isSpace Text
t) forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left String
"invalid code language: contains whitespace"
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> CodeLanguage
CodeLanguage Text
t

instance TTC.Render CodeLanguage where
  render :: forall t. Textual t => CodeLanguage -> t
render = forall t. Textual t => Text -> t
TTC.fromT forall b c a. (b -> c) -> (a -> b) -> a -> c
. CodeLanguage -> Text
unCodeLanguage