packages feed

axel-0.0.11: src/Axel/Utils/Text.hs

{-# 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))

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 a|]) . filter (/= '\r'))
    (error "Cannot use s as a pattern")
    (error "Cannot use s as a type")
    (error "Cannot use s as a dec")

handleCharEscapes :: Text -> Text
handleCharEscapes =
  T.concatMap $ \case
    '\\' -> "\\\\"
    c -> T.singleton c

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