content: {-# LANGUAGE TemplateHaskell #-}
  
  module Axel.Utils.Text where
  
  import Axel.Prelude
  
  import Control.Lens.Combinators (_head)
  import Control.Lens.Operators ((%~))
  
  import qualified Data.ByteString.Lazy as B
  import Data.Char (chr, ord, toUpper)
  import qualified Data.Text as T
  import qualified Data.Text.Encoding as T
  
  import GHC.Exts (IsString(fromString))
  
  import Language.Haskell.TH.Quote (QuasiQuoter(QuasiQuoter))
  import Language.Haskell.TH.Syntax (lift)
  
  capitalize :: Text -> Text
  capitalize = _head %~ toUpper
  
  -- Adapted from http://hackage.haskell.org/package/string-quote-0.0.1/docs/src/Data-String-Quote.html#s.
  s :: QuasiQuoter
  s =
    QuasiQuoter
      ((\a -> [|fromString $(lift a)|]) . filter (/= '\r'))
      (error "Cannot use s as a pattern")
      (error "Cannot use s as a type")
      (error "Cannot use s as a dec")
  
  -- TODO This renders very poorly in e.g. Fira Code Mono.
  bold :: Text -> Text
  bold = T.map boldCharacter
    where
      boldRanges = [('a', 'z', '𝗮'), ('A', 'Z', '𝗔'), ('0', '9', '𝟬')]
      boldDelta x =
        foldl
          (\acc (rangeStart, rangeEnd, boldStart) ->
             if x `elem` [rangeStart .. rangeEnd]
               then ord boldStart - ord rangeStart
               else acc)
          0
          boldRanges
      boldCharacter x = chr $ (+ boldDelta x) $ ord x
  
  indent :: Int -> Text -> Text
  indent width = T.unlines . map (T.replicate width " " <>) . T.lines
  
  type Renderer a = a -> Text
  
  encodeUtf8Lazy :: Text -> B.ByteString
  encodeUtf8Lazy = B.fromStrict . T.encodeUtf8
  
  decodeUtf8Lazy :: B.ByteString -> Text
  decodeUtf8Lazy = T.decodeUtf8 . B.toStrict
  
  remove :: Text -> Text -> Text
  remove needle = T.replace needle ""
  