<commit_before>{-# LANGUAGE CPP #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# OPTIONS_HADDOCK hide #-}

#ifndef MIN_VERSION_base
#defined MIN_VERSION_base(x,y,z) 1
#endif

module Graphics.Vty.Image.Internal where

import Graphics.Vty.Attributes
import Graphics.Text.Width

import Control.DeepSeq

import qualified Data.Text.Lazy as TL

#if !(MIN_VERSION_base(4,8,0))
import Data.Monoid
#endif

-- | A display text is a Data.Text.Lazy
--
-- TODO(corey): hm. there is an explicit equation for each type which goes to a lazy text. Each
-- application probably uses a single type. Perhaps parameterize the entire vty interface by the
-- input text type?
-- TODO: Try using a builder instead of a TL.Text instance directly. That might improve performance
-- for the usual case of appending a bunch of characters with the same attribute together.
type DisplayText = TL.Text

-- TODO: store a skip list in HorizText(?)
-- TODO: represent display strings containing chars that are not 1 column chars as a separate
-- display string value?
clipText :: DisplayText -> Int -> Int -> DisplayText
clipText txt leftSkip rightClip =
    -- CPS would clarify this I think
    let (toDrop,padPrefix) = clipForCharWidth leftSkip txt 0
        txt' = if padPrefix then TL.cons '…' (TL.drop (toDrop+1) txt) else TL.drop toDrop txt
        (toTake,padSuffix) = clipForCharWidth rightClip txt' 0
        txt'' = TL.append (TL.take toTake txt') (if padSuffix then TL.singleton '…' else TL.empty)
        -- Note: some characters and zero-width and combining characters
        -- combine to the left, so keep taking characters even if the width
        -- is zero.
        clipForCharWidth w t n
            | TL.null t = (n, False)
            | w < cw    = (n, w /= 0)
            | otherwise = clipForCharWidth (w - cw) (TL.tail t) (n + 1)
            where cw = safeWcwidth (TL.head t)
        clipForCharWidth _ _ _ = error "clipForCharWidth applied to undefined"
    in txt''

-- | This is the internal representation of Images. Use the constructors in "Graphics.Vty.Image" to
-- create instances.
--
-- Images are:
--
-- * a horizontal span of text
--
-- * a horizontal or vertical join of two images
--
-- * a two dimensional fill of the 'Picture's background character
--
-- * a cropped image
--
-- * an empty image of no size or content.
data Image = 
    -- | A horizontal text span is always >= 1 column and has a row height of 1.
      HorizText<commit_msg>Remove redundant clause from clipForCharWidth<commit_after>{-# LANGUAGE CPP #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# OPTIONS_HADDOCK hide #-}

#ifndef MIN_VERSION_base
#defined MIN_VERSION_base(x,y,z) 1
#endif

module Graphics.Vty.Image.Internal where

import Graphics.Vty.Attributes
import Graphics.Text.Width

import Control.DeepSeq

import qualified Data.Text.Lazy as TL

#if !(MIN_VERSION_base(4,8,0))
import Data.Monoid
#endif

-- | A display text is a Data.Text.Lazy
--
-- TODO(corey): hm. there is an explicit equation for each type which goes to a lazy text. Each
-- application probably uses a single type. Perhaps parameterize the entire vty interface by the
-- input text type?
-- TODO: Try using a builder instead of a TL.Text instance directly. That might improve performance
-- for the usual case of appending a bunch of characters with the same attribute together.
type DisplayText = TL.Text

-- TODO: store a skip list in HorizText(?)
-- TODO: represent display strings containing chars that are not 1 column chars as a separate
-- display string value?
clipText :: DisplayText -> Int -> Int -> DisplayText
clipText txt leftSkip rightClip =
    -- CPS would clarify this I think
    let (toDrop,padPrefix) = clipForCharWidth leftSkip txt 0
        txt' = if padPrefix then TL.cons '…' (TL.drop (toDrop+1) txt) else TL.drop toDrop txt
        (toTake,padSuffix) = clipForCharWidth rightClip txt' 0
        txt'' = TL.append (TL.take toTake txt') (if padSuffix then TL.singleton '…' else TL.empty)
        -- Note: some characters and zero-width and combining characters
        -- combine to the left, so keep taking characters even if the width
        -- is zero.
        clipForCharWidth w t n
            | TL.null t = (n, False)
            | w < cw    = (n, w /= 0)
            | otherwise = clipForCharWidth (w - cw) (TL.tail t) (n + 1)
            where cw = safeWcwidth (TL.head t)
    in txt''

-- | This is the internal representation of Images. Use the constructors in "Graphics.Vty.Image" to
-- create instances.
--
-- Images are:
--
-- * a horizontal span of text
--
-- * a horizontal or vertical join of two images
--
-- * a two dimensional fill of the 'Picture's background character
--
-- * a cropped image
--
-- * an empty image of no size or content.
data Image = 
    -- | A horizontal text span is always >= 1 column and has a row height of 1.
      HorizText
{'fraction_non_alphanumeric': 0.09576008273009307, 'fraction_numerical': 0.004963805584281282, 'mean_word_length': 2.896857373086221, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4919449', 'n_tokens_mistral': 1456, 'n_tokens_neox': 1417, 'n_words': 607}