    -- | Calculate the width of String and Text, being aware of wide characters.

    module Text.WideString (
      -- * Text Builders which keep track of length
      WideBuilder(..),
      wbUnpack,
      wbToText,
      wbFromText
      ) where

    import Data.Text (Text)
    import qualified Data.Text.Lazy as TL
    import qualified Data.Text.Lazy.Builder as TB
    import Text.DocLayout (realLength)

    -- | Helper for constructing Builders while keeping track of text width.
    data WideBuilder = WideBuilder
      { WideBuilder -> Builder
    wbBuilder :: !TB.Builder
      , WideBuilder -> Int
    wbWidth   :: !Int
      } deriving (Int -> WideBuilder -> ShowS
    [WideBuilder] -> ShowS
    WideBuilder -> String
    (Int -> WideBuilder -> ShowS)
    -> (WideBuilder -> String)
    -> ([WideBuilder] -> ShowS)
    -> Show WideBuilder
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> WideBuilder -> ShowS
    showsPrec :: Int -> WideBuilder -> ShowS
    $cshow :: WideBuilder -> String
    show :: WideBuilder -> String
    $cshowList :: [WideBuilder] -> ShowS
    showList :: [WideBuilder] -> ShowS
    Show)

    instance Semigroup WideBuilder where
      WideBuilder Builder
    x Int
    i <> :: WideBuilder -> WideBuilder -> WideBuilder
    <> WideBuilder Builder
    y Int
    j = Builder -> Int -> WideBuilder
    WideBuilder (Builder
    x Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Builder
    y) (Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    j)

    instance Monoid WideBuilder where
      mempty :: WideBuilder
    mempty = Builder -> Int -> WideBuilder
    WideBuilder Builder
    forall a. Monoid a => a
    mempty Int
    0

    -- | Convert a WideBuilder to a strict Text.
    wbToText :: WideBuilder -> Text
    wbToText :: WideBuilder -> Text
    wbToText = Text -> Text
    TL.toStrict (Text -> Text) -> (WideBuilder -> Text) -> WideBuilder -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    TB.toLazyText (Builder -> Text)
    -> (WideBuilder -> Builder) -> WideBuilder -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WideBuilder -> Builder
    wbBuilder

    -- | Convert a strict Text to a WideBuilder.
    wbFromText :: Text -> WideBuilder
    wbFromText :: Text -> WideBuilder
    wbFromText Text
    t = Builder -> Int -> WideBuilder
    WideBuilder (Text -> Builder
    TB.fromText Text
    t) (Text -> Int
    forall a. HasChars a => a -> Int
    realLength Text
    t)

    -- | Convert a WideBuilder to a String.
    wbUnpack :: WideBuilder -> String
    wbUnpack :: WideBuilder -> String
    wbUnpack = Text -> String
    TL.unpack (Text -> String) -> (WideBuilder -> Text) -> WideBuilder -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    TB.toLazyText (Builder -> Text)
    -> (WideBuilder -> Builder) -> WideBuilder -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WideBuilder -> Builder
    wbBuilder