module Client.Image.LineWrap (lineWrap, lineWrapChat) where
import Client.Image.PackedImage
import Data.Semigroup
import qualified Graphics.Vty.Image as Vty
import Graphics.Vty.Attributes
import qualified Data.Text.Lazy as L
lineWrap ::
Int ->
Vty.Image ->
Vty.Image
lineWrap w img
| Vty.imageWidth img == 0 = Vty.emptyImage
| Vty.imageWidth img <= w = terminate w img
| otherwise =
terminate w (Vty.cropRight w img) Vty.<->
lineWrap w (Vty.cropLeft (Vty.imageWidth img - w) img)
terminate ::
Int ->
Vty.Image ->
Vty.Image
terminate n img
| Vty.imageWidth img == n = img
| otherwise = img Vty.<|> Vty.char defAttr ' '
lineWrapChat ::
Int ->
Maybe Int ->
Image' ->
[Image']
lineWrapChat w (Just i)
| 2*i <= w = reverse . addPadding i . wordLineWrap w (w-i)
lineWrapChat w _ = reverse . wordLineWrap w w
addPadding :: Int -> [Image'] -> [Image']
addPadding _ [] = []
addPadding i (x:xs) = x : map indent xs
where indent = (string defAttr (replicate i ' ') <>)
wordLineWrap ::
Int ->
Int ->
Image' ->
[Image']
wordLineWrap w wNext img
| imgW == 0 = []
| imgW <= w = [img]
| otherwise = l : wordLineWrap wNext wNext (dropSpaces r)
where
imgW = imageWidth img
x:xs = splitOptions img
(l,r) = splitImage width img
width
| x <= w = go x xs
| otherwise = w
go y [] = min y w
go y (z:zs)
| z-y > wNext = w
| z > w = y
| otherwise = go z zs
splitOptions :: Image' -> [Int]
splitOptions
= dropWhile (0==)
. scanl1 (\x y -> 1 + x + y)
. map (Vty.wcswidth . L.unpack)
. L.split (' '==)
. imageText
dropSpaces :: Image' -> Image'
dropSpaces img
| n == 0 = img
| otherwise = snd (splitImage n img)
where
n = fromIntegral $ L.length $ L.takeWhile (' '==) $ imageText img