{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}

module System.Terminal.Emulator.TermLines
  ( TermLine,
    TermLines,
    empty,
    length,
    singleton,
    replicate,
    vIndex,
    head,
    last,
    take,
    takeLast,
    drop,
    dropLast,
    traverseWithIndex,
    toSeq,
  )
where

import Control.Exception (assert)
import Control.Lens
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import qualified Data.Vector.Unboxed as VU
import System.Terminal.Emulator.Attrs (Cell)
import Prelude hiding (drop, head, last, length, replicate, take)

type TermLine = VU.Vector Cell

type TermLines = StrictSeq TermLine

newtype StrictSeq a = StrictSeq (Seq a)
  deriving (Int -> StrictSeq a -> ShowS
[StrictSeq a] -> ShowS
StrictSeq a -> String
(Int -> StrictSeq a -> ShowS)
-> (StrictSeq a -> String)
-> ([StrictSeq a] -> ShowS)
-> Show (StrictSeq a)
forall a. Show a => Int -> StrictSeq a -> ShowS
forall a. Show a => [StrictSeq a] -> ShowS
forall a. Show a => StrictSeq a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StrictSeq a] -> ShowS
$cshowList :: forall a. Show a => [StrictSeq a] -> ShowS
show :: StrictSeq a -> String
$cshow :: forall a. Show a => StrictSeq a -> String
showsPrec :: Int -> StrictSeq a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> StrictSeq a -> ShowS
Show, StrictSeq a -> StrictSeq a -> Bool
(StrictSeq a -> StrictSeq a -> Bool)
-> (StrictSeq a -> StrictSeq a -> Bool) -> Eq (StrictSeq a)
forall a. Eq a => StrictSeq a -> StrictSeq a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StrictSeq a -> StrictSeq a -> Bool
$c/= :: forall a. Eq a => StrictSeq a -> StrictSeq a -> Bool
== :: StrictSeq a -> StrictSeq a -> Bool
$c== :: forall a. Eq a => StrictSeq a -> StrictSeq a -> Bool
Eq, Eq (StrictSeq a)
Eq (StrictSeq a)
-> (StrictSeq a -> StrictSeq a -> Ordering)
-> (StrictSeq a -> StrictSeq a -> Bool)
-> (StrictSeq a -> StrictSeq a -> Bool)
-> (StrictSeq a -> StrictSeq a -> Bool)
-> (StrictSeq a -> StrictSeq a -> Bool)
-> (StrictSeq a -> StrictSeq a -> StrictSeq a)
-> (StrictSeq a -> StrictSeq a -> StrictSeq a)
-> Ord (StrictSeq a)
StrictSeq a -> StrictSeq a -> Bool
StrictSeq a -> StrictSeq a -> Ordering
StrictSeq a -> StrictSeq a -> StrictSeq a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (StrictSeq a)
forall a. Ord a => StrictSeq a -> StrictSeq a -> Bool
forall a. Ord a => StrictSeq a -> StrictSeq a -> Ordering
forall a. Ord a => StrictSeq a -> StrictSeq a -> StrictSeq a
min :: StrictSeq a -> StrictSeq a -> StrictSeq a
$cmin :: forall a. Ord a => StrictSeq a -> StrictSeq a -> StrictSeq a
max :: StrictSeq a -> StrictSeq a -> StrictSeq a
$cmax :: forall a. Ord a => StrictSeq a -> StrictSeq a -> StrictSeq a
>= :: StrictSeq a -> StrictSeq a -> Bool
$c>= :: forall a. Ord a => StrictSeq a -> StrictSeq a -> Bool
> :: StrictSeq a -> StrictSeq a -> Bool
$c> :: forall a. Ord a => StrictSeq a -> StrictSeq a -> Bool
<= :: StrictSeq a -> StrictSeq a -> Bool
$c<= :: forall a. Ord a => StrictSeq a -> StrictSeq a -> Bool
< :: StrictSeq a -> StrictSeq a -> Bool
$c< :: forall a. Ord a => StrictSeq a -> StrictSeq a -> Bool
compare :: StrictSeq a -> StrictSeq a -> Ordering
$ccompare :: forall a. Ord a => StrictSeq a -> StrictSeq a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (StrictSeq a)
Ord, a -> StrictSeq b -> StrictSeq a
(a -> b) -> StrictSeq a -> StrictSeq b
(forall a b. (a -> b) -> StrictSeq a -> StrictSeq b)
-> (forall a b. a -> StrictSeq b -> StrictSeq a)
-> Functor StrictSeq
forall a b. a -> StrictSeq b -> StrictSeq a
forall a b. (a -> b) -> StrictSeq a -> StrictSeq b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> StrictSeq b -> StrictSeq a
$c<$ :: forall a b. a -> StrictSeq b -> StrictSeq a
fmap :: (a -> b) -> StrictSeq a -> StrictSeq b
$cfmap :: forall a b. (a -> b) -> StrictSeq a -> StrictSeq b
Functor, b -> StrictSeq a -> StrictSeq a
NonEmpty (StrictSeq a) -> StrictSeq a
StrictSeq a -> StrictSeq a -> StrictSeq a
(StrictSeq a -> StrictSeq a -> StrictSeq a)
-> (NonEmpty (StrictSeq a) -> StrictSeq a)
-> (forall b. Integral b => b -> StrictSeq a -> StrictSeq a)
-> Semigroup (StrictSeq a)
forall b. Integral b => b -> StrictSeq a -> StrictSeq a
forall a. NonEmpty (StrictSeq a) -> StrictSeq a
forall a. StrictSeq a -> StrictSeq a -> StrictSeq a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall a b. Integral b => b -> StrictSeq a -> StrictSeq a
stimes :: b -> StrictSeq a -> StrictSeq a
$cstimes :: forall a b. Integral b => b -> StrictSeq a -> StrictSeq a
sconcat :: NonEmpty (StrictSeq a) -> StrictSeq a
$csconcat :: forall a. NonEmpty (StrictSeq a) -> StrictSeq a
<> :: StrictSeq a -> StrictSeq a -> StrictSeq a
$c<> :: forall a. StrictSeq a -> StrictSeq a -> StrictSeq a
Semigroup, Semigroup (StrictSeq a)
StrictSeq a
Semigroup (StrictSeq a)
-> StrictSeq a
-> (StrictSeq a -> StrictSeq a -> StrictSeq a)
-> ([StrictSeq a] -> StrictSeq a)
-> Monoid (StrictSeq a)
[StrictSeq a] -> StrictSeq a
StrictSeq a -> StrictSeq a -> StrictSeq a
forall a. Semigroup (StrictSeq a)
forall a. StrictSeq a
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall a. [StrictSeq a] -> StrictSeq a
forall a. StrictSeq a -> StrictSeq a -> StrictSeq a
mconcat :: [StrictSeq a] -> StrictSeq a
$cmconcat :: forall a. [StrictSeq a] -> StrictSeq a
mappend :: StrictSeq a -> StrictSeq a -> StrictSeq a
$cmappend :: forall a. StrictSeq a -> StrictSeq a -> StrictSeq a
mempty :: StrictSeq a
$cmempty :: forall a. StrictSeq a
$cp1Monoid :: forall a. Semigroup (StrictSeq a)
Monoid, a -> StrictSeq a -> Bool
StrictSeq m -> m
StrictSeq a -> [a]
StrictSeq a -> Bool
StrictSeq a -> Int
StrictSeq a -> a
StrictSeq a -> a
StrictSeq a -> a
StrictSeq a -> a
(a -> m) -> StrictSeq a -> m
(a -> m) -> StrictSeq a -> m
(a -> b -> b) -> b -> StrictSeq a -> b
(a -> b -> b) -> b -> StrictSeq a -> b
(b -> a -> b) -> b -> StrictSeq a -> b
(b -> a -> b) -> b -> StrictSeq a -> b
(a -> a -> a) -> StrictSeq a -> a
(a -> a -> a) -> StrictSeq a -> a
(forall m. Monoid m => StrictSeq m -> m)
-> (forall m a. Monoid m => (a -> m) -> StrictSeq a -> m)
-> (forall m a. Monoid m => (a -> m) -> StrictSeq a -> m)
-> (forall a b. (a -> b -> b) -> b -> StrictSeq a -> b)
-> (forall a b. (a -> b -> b) -> b -> StrictSeq a -> b)
-> (forall b a. (b -> a -> b) -> b -> StrictSeq a -> b)
-> (forall b a. (b -> a -> b) -> b -> StrictSeq a -> b)
-> (forall a. (a -> a -> a) -> StrictSeq a -> a)
-> (forall a. (a -> a -> a) -> StrictSeq a -> a)
-> (forall a. StrictSeq a -> [a])
-> (forall a. StrictSeq a -> Bool)
-> (forall a. StrictSeq a -> Int)
-> (forall a. Eq a => a -> StrictSeq a -> Bool)
-> (forall a. Ord a => StrictSeq a -> a)
-> (forall a. Ord a => StrictSeq a -> a)
-> (forall a. Num a => StrictSeq a -> a)
-> (forall a. Num a => StrictSeq a -> a)
-> Foldable StrictSeq
forall a. Eq a => a -> StrictSeq a -> Bool
forall a. Num a => StrictSeq a -> a
forall a. Ord a => StrictSeq a -> a
forall m. Monoid m => StrictSeq m -> m
forall a. StrictSeq a -> Bool
forall a. StrictSeq a -> Int
forall a. StrictSeq a -> [a]
forall a. (a -> a -> a) -> StrictSeq a -> a
forall m a. Monoid m => (a -> m) -> StrictSeq a -> m
forall b a. (b -> a -> b) -> b -> StrictSeq a -> b
forall a b. (a -> b -> b) -> b -> StrictSeq a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: StrictSeq a -> a
$cproduct :: forall a. Num a => StrictSeq a -> a
sum :: StrictSeq a -> a
$csum :: forall a. Num a => StrictSeq a -> a
minimum :: StrictSeq a -> a
$cminimum :: forall a. Ord a => StrictSeq a -> a
maximum :: StrictSeq a -> a
$cmaximum :: forall a. Ord a => StrictSeq a -> a
elem :: a -> StrictSeq a -> Bool
$celem :: forall a. Eq a => a -> StrictSeq a -> Bool
length :: StrictSeq a -> Int
$clength :: forall a. StrictSeq a -> Int
null :: StrictSeq a -> Bool
$cnull :: forall a. StrictSeq a -> Bool
toList :: StrictSeq a -> [a]
$ctoList :: forall a. StrictSeq a -> [a]
foldl1 :: (a -> a -> a) -> StrictSeq a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> StrictSeq a -> a
foldr1 :: (a -> a -> a) -> StrictSeq a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> StrictSeq a -> a
foldl' :: (b -> a -> b) -> b -> StrictSeq a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> StrictSeq a -> b
foldl :: (b -> a -> b) -> b -> StrictSeq a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> StrictSeq a -> b
foldr' :: (a -> b -> b) -> b -> StrictSeq a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> StrictSeq a -> b
foldr :: (a -> b -> b) -> b -> StrictSeq a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> StrictSeq a -> b
foldMap' :: (a -> m) -> StrictSeq a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> StrictSeq a -> m
foldMap :: (a -> m) -> StrictSeq a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> StrictSeq a -> m
fold :: StrictSeq m -> m
$cfold :: forall m. Monoid m => StrictSeq m -> m
Foldable)

-- | The empty sequence.
empty :: StrictSeq a
empty :: StrictSeq a
empty = Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq Seq a
forall a. Seq a
Seq.empty
{-# INLINE empty #-}

-- | The number of elements in the sequence.
length :: StrictSeq a -> Int
length :: StrictSeq a -> Int
length (StrictSeq Seq a
v) = Seq a -> Int
forall a. Seq a -> Int
Seq.length Seq a
v
{-# INLINE length #-}

singleton :: a -> StrictSeq a
singleton :: a -> StrictSeq a
singleton a
x = a
x a -> StrictSeq a -> StrictSeq a
`seq` (Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (a -> Seq a
forall a. a -> Seq a
Seq.singleton a
x))
{-# INLINE singleton #-}

-- | @replicate n x@ is a sequence consisting of n copies of x.
replicate :: Int -> a -> StrictSeq a
replicate :: Int -> a -> StrictSeq a
replicate Int
n a
x = a
x a -> StrictSeq a -> StrictSeq a
`seq` (Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (Int -> a -> Seq a
forall a. Int -> a -> Seq a
Seq.replicate Int
n a
x))
{-# INLINE replicate #-}

-- | A lens to the specified index of the sequence. Must be in range.
vIndex :: Int -> Lens' (StrictSeq a) a
vIndex :: Int -> Lens' (StrictSeq a) a
vIndex Int
i =
  (StrictSeq a -> a)
-> (StrictSeq a -> a -> StrictSeq a) -> Lens' (StrictSeq a) a
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens StrictSeq a -> a
forall a. StrictSeq a -> a
getter StrictSeq a -> a -> StrictSeq a
forall a. StrictSeq a -> a -> StrictSeq a
setter
  where
    getter :: StrictSeq a -> a
    getter :: StrictSeq a -> a
getter (StrictSeq Seq a
v) = Bool -> a -> a
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Seq a -> Int
forall a. Seq a -> Int
Seq.length Seq a
v) (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ (Seq a -> Int -> a
forall a. Seq a -> Int -> a
`Seq.index` Int
i) Seq a
v
    setter :: StrictSeq a -> a -> StrictSeq a
    setter :: StrictSeq a -> a -> StrictSeq a
setter (StrictSeq Seq a
v) a
val = Bool -> StrictSeq a -> StrictSeq a
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Seq a -> Int
forall a. Seq a -> Int
Seq.length Seq a
v) (StrictSeq a -> StrictSeq a) -> StrictSeq a -> StrictSeq a
forall a b. (a -> b) -> a -> b
$ a
val a -> StrictSeq a -> StrictSeq a
`seq` (Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (Int -> a -> Seq a -> Seq a
forall a. Int -> a -> Seq a -> Seq a
Seq.update Int
i a
val Seq a
v))
    {-# INLINE getter #-}
    {-# INLINE setter #-}
{-# INLINE vIndex #-}

-- | First element. Must be nonempty
head :: StrictSeq a -> a
head :: StrictSeq a -> a
head (StrictSeq Seq a
v) = let a
x Seq.:< Seq a
_ = Seq a -> ViewL a
forall a. Seq a -> ViewL a
Seq.viewl Seq a
v in a
x
{-# INLINE head #-}

-- | Last element. Must be nonempty
last :: StrictSeq a -> a
last :: StrictSeq a -> a
last (StrictSeq Seq a
v) = let Seq a
_ Seq.:> a
x = Seq a -> ViewR a
forall a. Seq a -> ViewR a
Seq.viewr Seq a
v in a
x
{-# INLINE last #-}

-- | The first @i@ elements of a sequence. If @i@ is negative, @take i s@
-- yields the empty sequence. If the sequence contains fewer than @i@
-- elements, the whole sequence is returned.
take :: Int -> StrictSeq a -> StrictSeq a
take :: Int -> StrictSeq a -> StrictSeq a
take Int
i (StrictSeq Seq a
v) = Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (Int -> Seq a -> Seq a
forall a. Int -> Seq a -> Seq a
Seq.take Int
i Seq a
v)
{-# INLINE take #-}

-- | The last @i@ elements of a sequence. If @i@ is negative, @takeLast i s@
-- yields the empty sequence. If the sequence contains fewer than @i@
-- elements, the whole sequence is returned.
takeLast :: Int -> StrictSeq a -> StrictSeq a
takeLast :: Int -> StrictSeq a -> StrictSeq a
takeLast Int
i (StrictSeq Seq a
v) = Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (Int -> Seq a -> Seq a
forall a. Int -> Seq a -> Seq a
Seq.drop (Seq a -> Int
forall a. Seq a -> Int
Seq.length Seq a
v Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) Seq a
v)
{-# INLINE takeLast #-}

-- | Elements of a sequence after the first @i@. If @i@ is negative, @drop i
-- s@ yields the whole sequence. If the sequence contains fewer than @i@
-- elements, the empty sequence is returned.
drop :: Int -> StrictSeq a -> StrictSeq a
drop :: Int -> StrictSeq a -> StrictSeq a
drop Int
i (StrictSeq Seq a
v) = Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (Int -> Seq a -> Seq a
forall a. Int -> Seq a -> Seq a
Seq.drop Int
i Seq a
v)
{-# INLINE drop #-}

-- | Elements of a sequence after the first @i@ last elements. If @i@ is
-- negative, @dropLast i s@ yields the whole sequence. If the sequence
-- contains fewer than @i@ elements, the empty sequence is returned.
dropLast :: Int -> StrictSeq a -> StrictSeq a
dropLast :: Int -> StrictSeq a -> StrictSeq a
dropLast Int
i (StrictSeq Seq a
v) = Seq a -> StrictSeq a
forall a. Seq a -> StrictSeq a
StrictSeq (Int -> Seq a -> Seq a
forall a. Int -> Seq a -> Seq a
Seq.take (Seq a -> Int
forall a. Seq a -> Int
Seq.length Seq a
v Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) Seq a
v)
{-# INLINE dropLast #-}

-- | @traverseWithIndex@ is a version of @traverse@ that also offers access to
-- the index of each element.
traverseWithIndex :: Applicative f => (Int -> a -> f b) -> StrictSeq a -> f (StrictSeq b)
traverseWithIndex :: (Int -> a -> f b) -> StrictSeq a -> f (StrictSeq b)
traverseWithIndex Int -> a -> f b
f (StrictSeq Seq a
v) = Seq b -> StrictSeq b
forall a. Seq a -> StrictSeq a
StrictSeq (Seq b -> StrictSeq b) -> f (Seq b) -> f (StrictSeq b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Int -> a -> f b) -> Seq a -> f (Seq b)
forall (f :: * -> *) a b.
Applicative f =>
(Int -> a -> f b) -> Seq a -> f (Seq b)
Seq.traverseWithIndex Int -> a -> f b
f Seq a
v)
{-# INLINE traverseWithIndex #-}

toSeq :: StrictSeq a -> Seq a
toSeq :: StrictSeq a -> Seq a
toSeq (StrictSeq Seq a
v) = Seq a
v
{-# INLINE toSeq #-}