module Potato.Data.Text.Zipper where
import Prelude
import Control.Exception (assert)
import Control.Monad.State (evalState, get, put)
import Data.Char (isSpace)
import Data.Map (Map)
import Data.String
import Control.Monad
import Data.Text (Text)
import Data.Text.Internal (Text(..), text)
import Data.Text.Internal.Fusion (stream)
import Data.Text.Internal.Fusion.Types (Stream(..), Step(..))
import Data.Text.Unsafe
import qualified Data.List as L
import qualified Data.Map as Map
import qualified Data.Text as T
import Graphics.Text.Width (wcwidth)
data TextZipper = TextZipper
{ TextZipper -> [Text]
_textZipper_linesBefore :: [Text]
, TextZipper -> Text
_textZipper_before :: Text
, TextZipper -> Text
_textZipper_after :: Text
, TextZipper -> [Text]
_textZipper_linesAfter :: [Text]
}
deriving (Int -> TextZipper -> ShowS
[TextZipper] -> ShowS
TextZipper -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TextZipper] -> ShowS
$cshowList :: [TextZipper] -> ShowS
show :: TextZipper -> String
$cshow :: TextZipper -> String
showsPrec :: Int -> TextZipper -> ShowS
$cshowsPrec :: Int -> TextZipper -> ShowS
Show, TextZipper -> TextZipper -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TextZipper -> TextZipper -> Bool
$c/= :: TextZipper -> TextZipper -> Bool
== :: TextZipper -> TextZipper -> Bool
$c== :: TextZipper -> TextZipper -> Bool
Eq)
instance IsString TextZipper where
fromString :: String -> TextZipper
fromString = Text -> TextZipper
fromText forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack
mapZipper :: (Char -> Char) -> TextZipper -> TextZipper
mapZipper :: (Char -> Char) -> TextZipper -> TextZipper
mapZipper Char -> Char
f (TextZipper [Text]
lb Text
b Text
a [Text]
la) = TextZipper
{ _textZipper_linesBefore :: [Text]
_textZipper_linesBefore = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Char -> Char) -> Text -> Text
T.map Char -> Char
f) [Text]
lb
, _textZipper_before :: Text
_textZipper_before = (Char -> Char) -> Text -> Text
T.map Char -> Char
f Text
b
, _textZipper_after :: Text
_textZipper_after = (Char -> Char) -> Text -> Text
T.map Char -> Char
f Text
a
, _textZipper_linesAfter :: [Text]
_textZipper_linesAfter = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Char -> Char) -> Text -> Text
T.map Char -> Char
f) [Text]
la
}
left :: TextZipper -> TextZipper
left :: TextZipper -> TextZipper
left = Int -> TextZipper -> TextZipper
leftN Int
1
leftN :: Int -> TextZipper -> TextZipper
leftN :: Int -> TextZipper -> TextZipper
leftN Int
n z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) =
if Text -> Int
T.length Text
b forall a. Ord a => a -> a -> Bool
>= Int
n
then
let n' :: Int
n' = Text -> Int
T.length Text
b forall a. Num a => a -> a -> a
- Int
n
in [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb (Int -> Text -> Text
T.take Int
n' Text
b) (Int -> Text -> Text
T.drop Int
n' Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) [Text]
la
else case [Text]
lb of
[] -> TextZipper -> TextZipper
home TextZipper
z
(Text
l:[Text]
ls) -> Int -> TextZipper -> TextZipper
leftN (Int
n forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
b forall a. Num a => a -> a -> a
- Int
1) forall a b. (a -> b) -> a -> b
$ [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
ls Text
l Text
"" ((Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) forall a. a -> [a] -> [a]
: [Text]
la)
right :: TextZipper -> TextZipper
right :: TextZipper -> TextZipper
right = Int -> TextZipper -> TextZipper
rightN Int
1
rightN :: Int -> TextZipper -> TextZipper
rightN :: Int -> TextZipper -> TextZipper
rightN Int
n z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) =
if Text -> Int
T.length Text
a forall a. Ord a => a -> a -> Bool
>= Int
n
then [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb (Text
b forall a. Semigroup a => a -> a -> a
<> Int -> Text -> Text
T.take Int
n Text
a) (Int -> Text -> Text
T.drop Int
n Text
a) [Text]
la
else case [Text]
la of
[] -> TextZipper -> TextZipper
end TextZipper
z
(Text
l:[Text]
ls) -> Int -> TextZipper -> TextZipper
rightN (Int
n forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
a forall a. Num a => a -> a -> a
- Int
1) forall a b. (a -> b) -> a -> b
$ [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper ((Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) forall a. a -> [a] -> [a]
: [Text]
lb) Text
"" Text
l [Text]
ls
up :: TextZipper -> TextZipper
up :: TextZipper -> TextZipper
up z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) = case [Text]
lb of
[] -> TextZipper
z
(Text
l:[Text]
ls) ->
let (Text
b', Text
a') = Int -> Text -> (Text, Text)
T.splitAt (Text -> Int
T.length Text
b) Text
l
in [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
ls Text
b' Text
a' ((Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) forall a. a -> [a] -> [a]
: [Text]
la)
down :: TextZipper -> TextZipper
down :: TextZipper -> TextZipper
down z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) = case [Text]
la of
[] -> TextZipper
z
(Text
l:[Text]
ls) ->
let (Text
b', Text
a') = Int -> Text -> (Text, Text)
T.splitAt (Text -> Int
T.length Text
b) Text
l
in [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper ((Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) forall a. a -> [a] -> [a]
: [Text]
lb) Text
b' Text
a' [Text]
ls
pageUp :: Int -> TextZipper -> TextZipper
pageUp :: Int -> TextZipper -> TextZipper
pageUp Int
pageSize TextZipper
z = if Int
pageSize forall a. Ord a => a -> a -> Bool
<= Int
0
then TextZipper
z
else Int -> TextZipper -> TextZipper
pageUp (Int
pageSize forall a. Num a => a -> a -> a
- Int
1) forall a b. (a -> b) -> a -> b
$ TextZipper -> TextZipper
up TextZipper
z
pageDown :: Int -> TextZipper -> TextZipper
pageDown :: Int -> TextZipper -> TextZipper
pageDown Int
pageSize TextZipper
z = if Int
pageSize forall a. Ord a => a -> a -> Bool
<= Int
0
then TextZipper
z
else Int -> TextZipper -> TextZipper
pageDown (Int
pageSize forall a. Num a => a -> a -> a
- Int
1) forall a b. (a -> b) -> a -> b
$ TextZipper -> TextZipper
down TextZipper
z
home :: TextZipper -> TextZipper
home :: TextZipper -> TextZipper
home (TextZipper [Text]
lb Text
b Text
a [Text]
la) = [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb Text
"" (Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) [Text]
la
end :: TextZipper -> TextZipper
end :: TextZipper -> TextZipper
end (TextZipper [Text]
lb Text
b Text
a [Text]
la) = [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb (Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) Text
"" [Text]
la
top :: TextZipper -> TextZipper
top :: TextZipper -> TextZipper
top (TextZipper [Text]
lb Text
b Text
a [Text]
la) = case forall a. [a] -> [a]
reverse [Text]
lb of
[] -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [] Text
"" (Text
b forall a. Semigroup a => a -> a -> a
<> Text
a) [Text]
la
(Text
start:[Text]
rest) -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [] Text
"" Text
start ([Text]
rest forall a. Semigroup a => a -> a -> a
<> [Text
b forall a. Semigroup a => a -> a -> a
<> Text
a] forall a. Semigroup a => a -> a -> a
<> [Text]
la)
insertChar :: Char -> TextZipper -> TextZipper
insertChar :: Char -> TextZipper -> TextZipper
insertChar Char
i = Text -> TextZipper -> TextZipper
insert (Char -> Text
T.singleton Char
i)
insert :: Text -> TextZipper -> TextZipper
insert :: Text -> TextZipper -> TextZipper
insert Text
i z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) = case (Char -> Bool) -> Text -> [Text]
T.split (forall a. Eq a => a -> a -> Bool
==Char
'\n') Text
i of
[] -> TextZipper
z
(Text
start:[Text]
rest) -> case forall a. [a] -> [a]
reverse [Text]
rest of
[] -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb (Text
b forall a. Semigroup a => a -> a -> a
<> Text
start) Text
a [Text]
la
(Text
l:[Text]
ls) -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper ([Text]
ls forall a. Semigroup a => a -> a -> a
<> [Text
b forall a. Semigroup a => a -> a -> a
<> Text
start] forall a. Semigroup a => a -> a -> a
<> [Text]
lb) Text
l Text
a [Text]
la
deleteLeft :: TextZipper-> TextZipper
deleteLeft :: TextZipper -> TextZipper
deleteLeft z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) = case Text -> Maybe (Text, Char)
T.unsnoc Text
b of
Maybe (Text, Char)
Nothing -> case [Text]
lb of
[] -> TextZipper
z
(Text
l:[Text]
ls) -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
ls Text
l Text
a [Text]
la
Just (Text
b', Char
_) -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb Text
b' Text
a [Text]
la
deleteRight :: TextZipper -> TextZipper
deleteRight :: TextZipper -> TextZipper
deleteRight z :: TextZipper
z@(TextZipper [Text]
lb Text
b Text
a [Text]
la) = case Text -> Maybe (Char, Text)
T.uncons Text
a of
Maybe (Char, Text)
Nothing -> case [Text]
la of
[] -> TextZipper
z
(Text
l:[Text]
ls) -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb Text
b Text
l [Text]
ls
Just (Char
_, Text
a') -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb Text
b Text
a' [Text]
la
deleteLeftWord :: TextZipper -> TextZipper
deleteLeftWord :: TextZipper -> TextZipper
deleteLeftWord (TextZipper [Text]
lb Text
b Text
a [Text]
la) =
let b' :: Text
b' = (Char -> Bool) -> Text -> Text
T.dropWhileEnd Char -> Bool
isSpace Text
b
in if Text -> Bool
T.null Text
b'
then case [Text]
lb of
[] -> [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [] Text
b' Text
a [Text]
la
(Text
l:[Text]
ls) -> TextZipper -> TextZipper
deleteLeftWord forall a b. (a -> b) -> a -> b
$ [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
ls Text
l Text
a [Text]
la
else [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [Text]
lb ((Char -> Bool) -> Text -> Text
T.dropWhileEnd (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace) Text
b') Text
a [Text]
la
tab :: Int -> TextZipper -> TextZipper
tab :: Int -> TextZipper -> TextZipper
tab Int
n z :: TextZipper
z@(TextZipper [Text]
_ Text
b Text
_ [Text]
_) =
Text -> TextZipper -> TextZipper
insert (Int -> Text -> Text
T.replicate (forall a. Enum a => a -> Int
fromEnum forall a b. (a -> b) -> a -> b
$ Int
n forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
b forall a. Integral a => a -> a -> a
`mod` forall a. Ord a => a -> a -> a
max Int
1 Int
n) Text
" ") TextZipper
z
value :: TextZipper -> Text
value :: TextZipper -> Text
value (TextZipper [Text]
lb Text
b Text
a [Text]
la) = Text -> [Text] -> Text
T.intercalate Text
"\n" forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat [ forall a. [a] -> [a]
reverse [Text]
lb
, [Text
b forall a. Semigroup a => a -> a -> a
<> Text
a]
, [Text]
la
]
empty :: TextZipper
empty :: TextZipper
empty = [Text] -> Text -> Text -> [Text] -> TextZipper
TextZipper [] Text
"" Text
"" []
fromText :: Text -> TextZipper
fromText :: Text -> TextZipper
fromText = forall a b c. (a -> b -> c) -> b -> a -> c
flip Text -> TextZipper -> TextZipper
insert TextZipper
empty
data Span tag = Span tag Text
deriving (Span tag -> Span tag -> Bool
forall tag. Eq tag => Span tag -> Span tag -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Span tag -> Span tag -> Bool
$c/= :: forall tag. Eq tag => Span tag -> Span tag -> Bool
== :: Span tag -> Span tag -> Bool
$c== :: forall tag. Eq tag => Span tag -> Span tag -> Bool
Eq, Int -> Span tag -> ShowS
forall tag. Show tag => Int -> Span tag -> ShowS
forall tag. Show tag => [Span tag] -> ShowS
forall tag. Show tag => Span tag -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Span tag] -> ShowS
$cshowList :: forall tag. Show tag => [Span tag] -> ShowS
show :: Span tag -> String
$cshow :: forall tag. Show tag => Span tag -> String
showsPrec :: Int -> Span tag -> ShowS
$cshowsPrec :: forall tag. Show tag => Int -> Span tag -> ShowS
Show)
data TextAlignment =
TextAlignment_Left
| TextAlignment_Right
| TextAlignment_Center
deriving (TextAlignment -> TextAlignment -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TextAlignment -> TextAlignment -> Bool
$c/= :: TextAlignment -> TextAlignment -> Bool
== :: TextAlignment -> TextAlignment -> Bool
$c== :: TextAlignment -> TextAlignment -> Bool
Eq, Int -> TextAlignment -> ShowS
[TextAlignment] -> ShowS
TextAlignment -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TextAlignment] -> ShowS
$cshowList :: [TextAlignment] -> ShowS
show :: TextAlignment -> String
$cshow :: TextAlignment -> String
showsPrec :: Int -> TextAlignment -> ShowS
$cshowsPrec :: Int -> TextAlignment -> ShowS
Show)
type OffsetMapWithAlignment = Map Int (Int, Int)
data WrappedLine = WrappedLine
{ WrappedLine -> Text
_wrappedLines_text :: Text
, WrappedLine -> Bool
_wrappedLines_hiddenWhitespace :: Bool
, WrappedLine -> Int
_wrappedLines_offset :: Int
}
deriving (WrappedLine -> WrappedLine -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: WrappedLine -> WrappedLine -> Bool
$c/= :: WrappedLine -> WrappedLine -> Bool
== :: WrappedLine -> WrappedLine -> Bool
$c== :: WrappedLine -> WrappedLine -> Bool
Eq, Int -> WrappedLine -> ShowS
[WrappedLine] -> ShowS
WrappedLine -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [WrappedLine] -> ShowS
$cshowList :: [WrappedLine] -> ShowS
show :: WrappedLine -> String
$cshow :: WrappedLine -> String
showsPrec :: Int -> WrappedLine -> ShowS
$cshowsPrec :: Int -> WrappedLine -> ShowS
Show)
data DisplayLines tag = DisplayLines {
forall tag. DisplayLines tag -> [[Span tag]]
_displayLines_spans :: [[Span tag]]
, forall tag. DisplayLines tag -> OffsetMapWithAlignment
_displayLines_offsetMap :: OffsetMapWithAlignment
, forall tag. DisplayLines tag -> (Int, Int)
_displayLines_cursorPos :: (Int, Int)
}
deriving (DisplayLines tag -> DisplayLines tag -> Bool
forall tag. Eq tag => DisplayLines tag -> DisplayLines tag -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DisplayLines tag -> DisplayLines tag -> Bool
$c/= :: forall tag. Eq tag => DisplayLines tag -> DisplayLines tag -> Bool
== :: DisplayLines tag -> DisplayLines tag -> Bool
$c== :: forall tag. Eq tag => DisplayLines tag -> DisplayLines tag -> Bool
Eq, Int -> DisplayLines tag -> ShowS
forall tag. Show tag => Int -> DisplayLines tag -> ShowS
forall tag. Show tag => [DisplayLines tag] -> ShowS
forall tag. Show tag => DisplayLines tag -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DisplayLines tag] -> ShowS
$cshowList :: forall tag. Show tag => [DisplayLines tag] -> ShowS
show :: DisplayLines tag -> String
$cshow :: forall tag. Show tag => DisplayLines tag -> String
showsPrec :: Int -> DisplayLines tag -> ShowS
$cshowsPrec :: forall tag. Show tag => Int -> DisplayLines tag -> ShowS
Show)
splitAtWidth :: Int -> Text -> (Text, Text)
splitAtWidth :: Int -> Text -> (Text, Text)
splitAtWidth Int
n t :: Text
t@(Text Array
arr Int
off Int
len)
| Int
n forall a. Ord a => a -> a -> Bool
<= Int
0 = (Text
T.empty, Text
t)
| Int
n forall a. Ord a => a -> a -> Bool
>= Text -> Int
textWidth Text
t = (Text
t, Text
T.empty)
| Bool
otherwise = let k :: Int
k = Int -> Text -> Int
toLogicalIndex Int
n Text
t
in (Array -> Int -> Int -> Text
text Array
arr Int
off Int
k, Array -> Int -> Int -> Text
text Array
arr (Int
offforall a. Num a => a -> a -> a
+Int
k) (Int
lenforall a. Num a => a -> a -> a
-Int
k))
toLogicalIndex :: Int -> Text -> Int
toLogicalIndex :: Int -> Text -> Int
toLogicalIndex Int
n' t' :: Text
t'@(Text Array
_ Int
_ Int
len') = Int -> Int -> Int -> Int
loop Int
0 Int
0 Int
0
where loop :: Int -> Int -> Int -> Int
loop !Int
iteri !Int
li !Int
cumw
| Int
iteri forall a. Ord a => a -> a -> Bool
>= Int
len' = Int
liforall a. Num a => a -> a -> a
-Int
1
| Int
cumw forall a. Num a => a -> a -> a
+ Int
w forall a. Ord a => a -> a -> Bool
> Int
n' = Int
li
| Bool
otherwise = Int -> Int -> Int -> Int
loop (Int
iteriforall a. Num a => a -> a -> a
+Int
d) (Int
liforall a. Num a => a -> a -> a
+Int
1) (Int
cumw forall a. Num a => a -> a -> a
+ Int
w)
where Iter Char
c Int
d = Text -> Int -> Iter
iter Text
t' Int
iteri
w :: Int
w = Char -> Int
charWidth Char
c
takeWidth :: Int -> Text -> Text
takeWidth :: Int -> Text -> Text
takeWidth Int
n = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> (Text, Text)
splitAtWidth Int
n
dropWidth :: Int -> Text -> Text
dropWidth :: Int -> Text -> Text
dropWidth Int
n = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> (Text, Text)
splitAtWidth Int
n
charWidth :: Char -> Int
charWidth :: Char -> Int
charWidth = Char -> Int
wcwidth
spansWidth :: [Span tag] -> Int
spansWidth :: forall tag. [Span tag] -> Int
spansWidth = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (\(Span tag
_ Text
t) -> Text -> Int
textWidth Text
t)
spansLength :: [Span tag] -> Int
spansLength :: forall tag. [Span tag] -> Int
spansLength = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (\(Span tag
_ Text
t) -> Text -> Int
T.length Text
t)
textWidth :: Text -> Int
textWidth :: Text -> Int
textWidth Text
t = Stream Char -> Int
widthI (Text -> Stream Char
stream Text
t)
widthI :: Stream Char -> Int
widthI :: Stream Char -> Int
widthI (Stream s -> Step s Char
next s
s0 Size
_len) = Int -> s -> Int
loop_length Int
0 s
s0
where
loop_length :: Int -> s -> Int
loop_length !Int
z s
s = case s -> Step s Char
next s
s of
Step s Char
Done -> Int
z
Skip s
s' -> Int -> s -> Int
loop_length Int
z s
s'
Yield Char
c s
s' -> Int -> s -> Int
loop_length (Int
z forall a. Num a => a -> a -> a
+ Char -> Int
charWidth Char
c) s
s'
{-# INLINE[0] widthI #-}
charIndexAt :: Int -> Stream Char -> Int
charIndexAt :: Int -> Stream Char -> Int
charIndexAt Int
pos (Stream s -> Step s Char
next s
s0 Size
_len) = Int -> Int -> s -> Int
loop_length Int
0 Int
0 s
s0
where
loop_length :: Int -> Int -> s -> Int
loop_length Int
i !Int
z s
s = case s -> Step s Char
next s
s of
Step s Char
Done -> Int
i
Skip s
s' -> Int -> Int -> s -> Int
loop_length Int
i Int
z s
s'
Yield Char
c s
s' -> if Int
w forall a. Ord a => a -> a -> Bool
> Int
pos then Int
i else Int -> Int -> s -> Int
loop_length (Int
iforall a. Num a => a -> a -> a
+Int
1) Int
w s
s' where
w :: Int
w = Int
z forall a. Num a => a -> a -> a
+ Char -> Int
charWidth Char
c
{-# INLINE[0] charIndexAt #-}
wordsWithWhitespace :: Text -> [Text]
wordsWithWhitespace :: Text -> [Text]
wordsWithWhitespace t :: Text
t@(Text Array
arr Int
off Int
len) = Int -> Int -> Bool -> [Text]
loop Int
0 Int
0 Bool
False
where
loop :: Int -> Int -> Bool -> [Text]
loop !Int
start !Int
n !Bool
wasSpace
| Int
n forall a. Ord a => a -> a -> Bool
>= Int
len = [Array -> Int -> Int -> Text
Text Array
arr (Int
startforall a. Num a => a -> a -> a
+Int
off) (Int
nforall a. Num a => a -> a -> a
-Int
start) | Bool -> Bool
not (Int
start forall a. Eq a => a -> a -> Bool
== Int
n)]
| Char -> Bool
isSpace Char
c = Int -> Int -> Bool -> [Text]
loop Int
start (Int
nforall a. Num a => a -> a -> a
+Int
d) Bool
True
| Bool
wasSpace = Array -> Int -> Int -> Text
Text Array
arr (Int
startforall a. Num a => a -> a -> a
+Int
off) (Int
nforall a. Num a => a -> a -> a
-Int
start) forall a. a -> [a] -> [a]
: Int -> Int -> Bool -> [Text]
loop Int
n Int
n Bool
False
| Bool
otherwise = Int -> Int -> Bool -> [Text]
loop Int
start (Int
nforall a. Num a => a -> a -> a
+Int
d) Bool
False
where Iter Char
c Int
d = Text -> Int -> Iter
iter Text
t Int
n
{-# INLINE wordsWithWhitespace #-}
splitWordsAtDisplayWidth :: Int -> [Text] -> [(Text, Bool)]
splitWordsAtDisplayWidth :: Int -> [Text] -> [(Text, Bool)]
splitWordsAtDisplayWidth Int
maxWidth [Text]
wwws = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ [Text] -> Int -> [(Text, Bool)] -> [(Text, Bool)]
loop [Text]
wwws Int
0 [] where
appendOut :: [(Text,Bool)] -> Text -> Bool -> [(Text,Bool)]
appendOut :: [(Text, Bool)] -> Text -> Bool -> [(Text, Bool)]
appendOut [] Text
t Bool
b = [(Text
t,Bool
b)]
appendOut ((Text
t',Bool
_):[(Text, Bool)]
ts') Text
t Bool
b = (Text
t'forall a. Semigroup a => a -> a -> a
<>Text
t,Bool
b) forall a. a -> [a] -> [a]
: [(Text, Bool)]
ts'
modifyOutForNewLine :: [(Text,Bool)] -> [(Text,Bool)]
modifyOutForNewLine :: [(Text, Bool)] -> [(Text, Bool)]
modifyOutForNewLine [] = forall a. HasCallStack => String -> a
error String
"should never happen"
modifyOutForNewLine ((Text
t',Bool
_):[(Text, Bool)]
ts) = case Text -> Maybe (Text, Char)
T.unsnoc Text
t' of
Maybe (Text, Char)
Nothing -> forall a. HasCallStack => String -> a
error String
"should never happen"
Just (Text
t,Char
lastChar) -> forall a. HasCallStack => Bool -> a -> a
assert (Char -> Bool
isSpace Char
lastChar) forall a b. (a -> b) -> a -> b
$ (Text
t,Bool
True)forall a. a -> [a] -> [a]
:[(Text, Bool)]
ts
loop :: [Text] -> Int -> [(Text,Bool)] -> [(Text,Bool)]
loop :: [Text] -> Int -> [(Text, Bool)] -> [(Text, Bool)]
loop [] Int
_ [(Text, Bool)]
out = [(Text, Bool)]
out
loop (Text
x:[Text]
xs) Int
cumw [(Text, Bool)]
out = [(Text, Bool)]
r where
newWidth :: Int
newWidth = Text -> Int
textWidth Text
x forall a. Num a => a -> a -> a
+ Int
cumw
r :: [(Text, Bool)]
r = if Int
newWidth forall a. Ord a => a -> a -> Bool
> Int
maxWidth
then if Char -> Bool
isSpace forall a b. (a -> b) -> a -> b
$ Text -> Int -> Char
T.index Text
x (Int -> Text -> Int
toLogicalIndex (Int
maxWidth forall a. Num a => a -> a -> a
- Int
cumw) Text
x)
then let (Text
t1,Text
t2) = Int -> Text -> (Text, Text)
splitAtWidth (Int
maxWidth forall a. Num a => a -> a -> a
- Int
cumw) Text
x
in [Text] -> Int -> [(Text, Bool)] -> [(Text, Bool)]
loop (Int -> Text -> Text
T.drop Int
1 Text
t2forall a. a -> [a] -> [a]
:[Text]
xs) Int
0 [] forall a. Semigroup a => a -> a -> a
<> [(Text, Bool)] -> Text -> Bool -> [(Text, Bool)]
appendOut [(Text, Bool)]
out Text
t1 Bool
True
else if Int
cumw forall a. Eq a => a -> a -> Bool
== Int
0
then let (Text
t1,Text
t2) = Int -> Text -> (Text, Text)
splitAtWidth (Int
maxWidth forall a. Num a => a -> a -> a
- Int
cumw) Text
x
in [Text] -> Int -> [(Text, Bool)] -> [(Text, Bool)]
loop (Text
t2forall a. a -> [a] -> [a]
:[Text]
xs) Int
0 [] forall a. Semigroup a => a -> a -> a
<> [(Text, Bool)] -> Text -> Bool -> [(Text, Bool)]
appendOut [(Text, Bool)]
out Text
t1 Bool
False
else [Text] -> Int -> [(Text, Bool)] -> [(Text, Bool)]
loop (Text
xforall a. a -> [a] -> [a]
:[Text]
xs) Int
0 [] forall a. Semigroup a => a -> a -> a
<> [(Text, Bool)] -> [(Text, Bool)]
modifyOutForNewLine [(Text, Bool)]
out
else [Text] -> Int -> [(Text, Bool)] -> [(Text, Bool)]
loop [Text]
xs Int
newWidth forall a b. (a -> b) -> a -> b
$ [(Text, Bool)] -> Text -> Bool -> [(Text, Bool)]
appendOut [(Text, Bool)]
out Text
x Bool
False
alignmentOffset ::
TextAlignment
-> Int
-> Text
-> Int
alignmentOffset :: TextAlignment -> Int -> Text -> Int
alignmentOffset TextAlignment
alignment Int
maxWidth Text
t = case TextAlignment
alignment of
TextAlignment
TextAlignment_Left -> Int
0
TextAlignment
TextAlignment_Right -> (Int
maxWidth forall a. Num a => a -> a -> a
- Int
l)
TextAlignment
TextAlignment_Center -> (Int
maxWidth forall a. Num a => a -> a -> a
- Int
l) forall a. Integral a => a -> a -> a
`div` Int
2
where
l :: Int
l = Text -> Int
textWidth Text
t
wrapWithOffsetAndAlignment
:: TextAlignment
-> Int
-> Int
-> Text
-> [WrappedLine]
wrapWithOffsetAndAlignment :: TextAlignment -> Int -> Int -> Text -> [WrappedLine]
wrapWithOffsetAndAlignment TextAlignment
_ Int
maxWidth Int
_ Text
_ | Int
maxWidth forall a. Ord a => a -> a -> Bool
<= Int
0 = []
wrapWithOffsetAndAlignment TextAlignment
alignment Int
maxWidth Int
n Text
txt = forall a. HasCallStack => Bool -> a -> a
assert (Int
n forall a. Ord a => a -> a -> Bool
<= Int
maxWidth) [WrappedLine]
r where
r' :: [(Text, Bool)]
r' = if Text -> Bool
T.null Text
txt
then [(Text
"",Bool
False)]
else Int -> [Text] -> [(Text, Bool)]
splitWordsAtDisplayWidth Int
maxWidth forall a b. (a -> b) -> a -> b
$ Text -> [Text]
wordsWithWhitespace ( Int -> Text -> Text
T.replicate Int
n Text
"." forall a. Semigroup a => a -> a -> a
<> Text
txt)
fmapfn :: (Text, Bool) -> WrappedLine
fmapfn (Text
t,Bool
b) = Text -> Bool -> Int -> WrappedLine
WrappedLine Text
t Bool
b forall a b. (a -> b) -> a -> b
$ TextAlignment -> Int -> Text -> Int
alignmentOffset TextAlignment
alignment Int
maxWidth Text
t
r'' :: [(Text, Bool)]
r'' = case [(Text, Bool)]
r' of
[] -> []
(Text
x,Bool
b):[(Text, Bool)]
xs -> (Int -> Text -> Text
T.drop Int
n Text
x,Bool
b)forall a. a -> [a] -> [a]
:[(Text, Bool)]
xs
r :: [WrappedLine]
r = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text, Bool) -> WrappedLine
fmapfn [(Text, Bool)]
r''
eolSpacesToLogicalLines :: [[WrappedLine]] -> [[(Text, Int)]]
eolSpacesToLogicalLines :: [[WrappedLine]] -> [[(Text, Int)]]
eolSpacesToLogicalLines = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(WrappedLine Text
a Bool
_ Int
c) -> (Text
a,Int
c))) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a. (a -> a -> Bool) -> [a] -> [[a]]
L.groupBy (\(WrappedLine Text
_ Bool
b Int
_) WrappedLine
_ -> Bool -> Bool
not Bool
b))
offsetMapWithAlignmentInternal :: [[WrappedLine]] -> OffsetMapWithAlignment
offsetMapWithAlignmentInternal :: [[WrappedLine]] -> OffsetMapWithAlignment
offsetMapWithAlignmentInternal = [[(Text, Int)]] -> OffsetMapWithAlignment
offsetMapWithAlignment forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[WrappedLine]] -> [[(Text, Int)]]
eolSpacesToLogicalLines
offsetMapWithAlignment
:: [[(Text, Int)]]
-> OffsetMapWithAlignment
offsetMapWithAlignment :: [[(Text, Int)]] -> OffsetMapWithAlignment
offsetMapWithAlignment [[(Text, Int)]]
ts = forall s a. State s a -> s -> a
evalState (forall {k} {f :: * -> *} {f :: * -> *} {f :: * -> *} {a}.
(Ord k, Traversable f, Traversable f, MonadState (k, Int) f,
Num k) =>
f (f (Text, a)) -> f (Map k (a, Int))
offsetMap' [[(Text, Int)]]
ts) (Int
0, Int
0)
where
offsetMap' :: f (f (Text, a)) -> f (Map k (a, Int))
offsetMap' f (f (Text, a))
xs = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
Map.unions forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM f (f (Text, a))
xs forall a b. (a -> b) -> a -> b
$ \f (Text, a)
x -> do
f (Map k (a, Int))
maps <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM f (Text, a)
x forall a b. (a -> b) -> a -> b
$ \(Text
line,a
align) -> do
let l :: Int
l = Text -> Int
T.length Text
line
(k
dl, Int
o) <- forall s (m :: * -> *). MonadState s m => m s
get
forall s (m :: * -> *). MonadState s m => s -> m ()
put (k
dl forall a. Num a => a -> a -> a
+ k
1, Int
o forall a. Num a => a -> a -> a
+ Int
l)
return $ forall k a. k -> a -> Map k a
Map.singleton k
dl (a
align, Int
o)
(k
dl, Int
o) <- forall s (m :: * -> *). MonadState s m => m s
get
forall s (m :: * -> *). MonadState s m => s -> m ()
put (k
dl, Int
o forall a. Num a => a -> a -> a
+ Int
1)
return $ forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
Map.adjust (\(a
align,Int
_)->(a
align,Int
oforall a. Num a => a -> a -> a
+Int
1)) k
dl forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
Map.unions f (Map k (a, Int))
maps
displayLinesWithAlignment
:: TextAlignment
-> Int
-> tag
-> tag
-> TextZipper
-> DisplayLines tag
displayLinesWithAlignment :: forall tag.
TextAlignment
-> Int -> tag -> tag -> TextZipper -> DisplayLines tag
displayLinesWithAlignment TextAlignment
alignment Int
width tag
tag tag
cursorTag (TextZipper [Text]
lb Text
b Text
a [Text]
la) =
let
linesBefore :: [[WrappedLine]]
linesBefore :: [[WrappedLine]]
linesBefore = forall a b. (a -> b) -> [a] -> [b]
map (TextAlignment -> Int -> Int -> Text -> [WrappedLine]
wrapWithOffsetAndAlignment TextAlignment
alignment Int
width Int
0) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [Text]
lb
linesAfter :: [[WrappedLine]]
linesAfter :: [[WrappedLine]]
linesAfter = forall a b. (a -> b) -> [a] -> [b]
map (TextAlignment -> Int -> Int -> Text -> [WrappedLine]
wrapWithOffsetAndAlignment TextAlignment
alignment Int
width Int
0) [Text]
la
afterWithCursor :: Text
afterWithCursor = if Text -> Bool
T.null Text
a then Text
" " else Text
a
offsets :: OffsetMapWithAlignment
offsets :: OffsetMapWithAlignment
offsets = [[WrappedLine]] -> OffsetMapWithAlignment
offsetMapWithAlignmentInternal forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat
[ [[WrappedLine]]
linesBefore
, [TextAlignment -> Int -> Int -> Text -> [WrappedLine]
wrapWithOffsetAndAlignment TextAlignment
alignment Int
width Int
0 forall a b. (a -> b) -> a -> b
$ Text
b forall a. Semigroup a => a -> a -> a
<> Text
afterWithCursor]
, [[WrappedLine]]
linesAfter
]
flattenLines :: [[WrappedLine]] -> [Text]
flattenLines = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WrappedLine -> Text
_wrappedLines_text)
spansBefore :: [[Span tag]]
spansBefore = forall a b. (a -> b) -> [a] -> [b]
map ((forall a. a -> [a] -> [a]
:[]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall tag. tag -> Text -> Span tag
Span tag
tag) forall a b. (a -> b) -> a -> b
$ [[WrappedLine]] -> [Text]
flattenLines [[WrappedLine]]
linesBefore
spansAfter :: [[Span tag]]
spansAfter = forall a b. (a -> b) -> [a] -> [b]
map ((forall a. a -> [a] -> [a]
:[]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall tag. tag -> Text -> Span tag
Span tag
tag) forall a b. (a -> b) -> a -> b
$ [[WrappedLine]] -> [Text]
flattenLines [[WrappedLine]]
linesAfter
curlinetext :: Text
curlinetext = Text
b forall a. Semigroup a => a -> a -> a
<> Text
a
curwrappedlines :: [WrappedLine]
curwrappedlines = (TextAlignment -> Int -> Int -> Text -> [WrappedLine]
wrapWithOffsetAndAlignment TextAlignment
alignment Int
width Int
0 Text
curlinetext)
blength :: Int
blength = Text -> Int
T.length Text
b
mapaccumlfn :: (Int, Either Int (Int, Int))
-> WrappedLine -> ((Int, Either Int (Int, Int)), [Span tag])
mapaccumlfn (Int
acclength, Either Int (Int, Int)
ecpos) (WrappedLine Text
t Bool
dwseol Int
xoff) = ((Int, Either Int (Int, Int)), [Span tag])
r where
tlength :: Int
tlength = Text -> Int
T.length Text
t
nextacclength :: Int
nextacclength = Int
acclength forall a. Num a => a -> a -> a
+ Int
tlength forall a. Num a => a -> a -> a
+ if Bool
dwseol then Int
1 else Int
0
nextacc :: (Int, Either Int (Int, Int))
nextacc = (Int
nextacclength, Either Int (Int, Int)
nextecpos)
cursoroncurspan :: Bool
cursoroncurspan = Int
nextacclength forall a. Ord a => a -> a -> Bool
>= Int
blength Bool -> Bool -> Bool
&& (Int
blength forall a. Ord a => a -> a -> Bool
>= Int
acclength)
charsbeforecursor :: Int
charsbeforecursor = Int
blengthforall a. Num a => a -> a -> a
-Int
acclength
ctlength :: Int
ctlength = Text -> Int
textWidth forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.take Int
charsbeforecursor Text
t
cursorx :: Int
cursorx = Int
xoff forall a. Num a => a -> a -> a
+ Int
ctlength
nextecpos :: Either Int (Int, Int)
nextecpos = case Either Int (Int, Int)
ecpos of
Left Int
y -> if Bool
cursoroncurspan
then if Int
ctlength forall a. Eq a => a -> a -> Bool
== Int
width
then forall a b. b -> Either a b
Right (Int
yforall a. Num a => a -> a -> a
+Int
1, Int
0)
else forall a b. b -> Either a b
Right (Int
y, Int
cursorx)
else forall a b. a -> Either a b
Left (Int
yforall a. Num a => a -> a -> a
+Int
1)
Right (Int, Int)
x -> forall a b. b -> Either a b
Right (Int, Int)
x
beforecursor :: Text
beforecursor = Int -> Text -> Text
T.take Int
charsbeforecursor Text
t
cursortext :: Text
cursortext = Int -> Text -> Text
T.take Int
1 forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.drop Int
charsbeforecursor Text
t
aftercursor :: Text
aftercursor = Int -> Text -> Text
T.drop (Int
charsbeforecursorforall a. Num a => a -> a -> a
+Int
1) Text
t
cursorspans :: [Span tag]
cursorspans = [forall tag. tag -> Text -> Span tag
Span tag
tag Text
beforecursor, forall tag. tag -> Text -> Span tag
Span tag
cursorTag Text
cursortext] forall a. Semigroup a => a -> a -> a
<> if Text -> Bool
T.null Text
aftercursor then [] else [forall tag. tag -> Text -> Span tag
Span tag
tag Text
aftercursor]
r :: ((Int, Either Int (Int, Int)), [Span tag])
r = if Bool
cursoroncurspan
then ((Int, Either Int (Int, Int))
nextacc, [Span tag]
cursorspans)
else ((Int, Either Int (Int, Int))
nextacc, [forall tag. tag -> Text -> Span tag
Span tag
tag Text
t])
((Int
_, Either Int (Int, Int)
ecpos_out), [[Span tag]]
curlinespans) = if Text -> Bool
T.null Text
curlinetext
then ((Int
0, forall a b. b -> Either a b
Right (Int
0, TextAlignment -> Int -> Text -> Int
alignmentOffset TextAlignment
alignment Int
width Text
"")), [[forall tag. tag -> Text -> Span tag
Span tag
cursorTag Text
""]])
else forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
L.mapAccumL (Int, Either Int (Int, Int))
-> WrappedLine -> ((Int, Either Int (Int, Int)), [Span tag])
mapaccumlfn (Int
0, forall a b. a -> Either a b
Left Int
0) [WrappedLine]
curwrappedlines
(Int
cursorY', Int
cursorX) = case Either Int (Int, Int)
ecpos_out of
Right (Int
y,Int
x) -> (Int
y,Int
x)
Left Int
y -> (Int
yforall a. Num a => a -> a -> a
+Int
1, TextAlignment -> Int -> Text -> Int
alignmentOffset TextAlignment
alignment Int
width Text
"")
cursorY :: Int
cursorY = Int
cursorY' forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Span tag]]
spansBefore
in DisplayLines
{ _displayLines_spans :: [[Span tag]]
_displayLines_spans = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [[Span tag]]
spansBefore
, [[Span tag]]
curlinespans
, [[Span tag]]
spansAfter
]
, _displayLines_offsetMap :: OffsetMapWithAlignment
_displayLines_offsetMap = OffsetMapWithAlignment
offsets
, _displayLines_cursorPos :: (Int, Int)
_displayLines_cursorPos = (Int
cursorX, Int
cursorY)
}
goToDisplayLinePosition :: Int -> Int -> DisplayLines tag -> TextZipper -> TextZipper
goToDisplayLinePosition :: forall tag.
Int -> Int -> DisplayLines tag -> TextZipper -> TextZipper
goToDisplayLinePosition Int
x Int
y DisplayLines tag
dl TextZipper
tz =
let offset :: Maybe (Int, Int)
offset = forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Int
y forall a b. (a -> b) -> a -> b
$ forall tag. DisplayLines tag -> OffsetMapWithAlignment
_displayLines_offsetMap DisplayLines tag
dl
in case Maybe (Int, Int)
offset of
Maybe (Int, Int)
Nothing -> TextZipper
tz
Just (Int
alignOff,Int
o) ->
let
trueX :: Int
trueX = forall a. Ord a => a -> a -> a
max Int
0 (Int
x forall a. Num a => a -> a -> a
- Int
alignOff)
moveRight :: Int
moveRight = case forall a. Int -> [a] -> [a]
drop Int
y forall a b. (a -> b) -> a -> b
$ forall tag. DisplayLines tag -> [[Span tag]]
_displayLines_spans DisplayLines tag
dl of
[] -> Int
0
([Span tag]
s:[[Span tag]]
_) -> Int -> Stream Char -> Int
charIndexAt Int
trueX forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Stream Char
stream forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Span tag
_ Text
t) -> Text
t) forall a b. (a -> b) -> a -> b
$ [Span tag]
s
in Int -> TextZipper -> TextZipper
rightN (Int
o forall a. Num a => a -> a -> a
+ Int
moveRight) forall a b. (a -> b) -> a -> b
$ TextZipper -> TextZipper
top TextZipper
tz
displayLines
:: Int
-> tag
-> tag
-> TextZipper
-> DisplayLines tag
displayLines :: forall tag. Int -> tag -> tag -> TextZipper -> DisplayLines tag
displayLines = forall tag.
TextAlignment
-> Int -> tag -> tag -> TextZipper -> DisplayLines tag
displayLinesWithAlignment TextAlignment
TextAlignment_Left
wrapWithOffset
:: Int
-> Int
-> Text
-> [Text]
wrapWithOffset :: Int -> Int -> Text -> [Text]
wrapWithOffset Int
maxWidth Int
n Text
xs = WrappedLine -> Text
_wrappedLines_text forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TextAlignment -> Int -> Int -> Text -> [WrappedLine]
wrapWithOffsetAndAlignment TextAlignment
TextAlignment_Left Int
maxWidth Int
n Text
xs