module System.Console.Haskeline.Backend.WCWidth(
gsWidth,
splitAtWidth,
takeWidth,
) where
import System.Console.Haskeline.LineState
import Data.List (foldl')
import Foreign.C.Types
foreign import ccall unsafe haskeline_mk_wcwidth :: CInt -> CInt
wcwidth :: Char -> Int
wcwidth :: Char -> Int
wcwidth Char
c = case CInt -> CInt
haskeline_mk_wcwidth (CInt -> CInt) -> CInt -> CInt
forall a b. (a -> b) -> a -> b
$ Int -> CInt
forall a. Enum a => Int -> a
toEnum (Int -> CInt) -> Int -> CInt
forall a b. (a -> b) -> a -> b
$ Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
c of
-1 -> Int
0
CInt
w -> CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
w
gWidth :: Grapheme -> Int
gWidth :: Grapheme -> Int
gWidth Grapheme
g = Char -> Int
wcwidth (Grapheme -> Char
baseChar Grapheme
g)
gsWidth :: [Grapheme] -> Int
gsWidth :: [Grapheme] -> Int
gsWidth = (Int -> Int -> Int) -> Int -> [Int] -> Int
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) Int
0 ([Int] -> Int) -> ([Grapheme] -> [Int]) -> [Grapheme] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Grapheme -> Int) -> [Grapheme] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Grapheme -> Int
gWidth
splitAtWidth :: Int -> [Grapheme] -> ([Grapheme],[Grapheme],Int)
splitAtWidth :: Int -> [Grapheme] -> ([Grapheme], [Grapheme], Int)
splitAtWidth Int
n [Grapheme]
xs = case Int -> [Grapheme] -> ([Grapheme], [Grapheme], Int)
splitAtWidth' Int
n [Grapheme]
xs of
([Grapheme]
this,[Grapheme]
rest,Int
remaining) -> ([Grapheme]
this,[Grapheme]
rest,Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
remaining)
splitAtWidth' :: Int -> [Grapheme] -> ([Grapheme],[Grapheme],Int)
splitAtWidth' :: Int -> [Grapheme] -> ([Grapheme], [Grapheme], Int)
splitAtWidth' Int
w [] = ([],[],Int
w)
splitAtWidth' Int
w (Grapheme
g:[Grapheme]
gs)
| Int
gw Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
w = ([],Grapheme
gGrapheme -> [Grapheme] -> [Grapheme]
forall a. a -> [a] -> [a]
:[Grapheme]
gs,Int
w)
| Bool
otherwise = (Grapheme
gGrapheme -> [Grapheme] -> [Grapheme]
forall a. a -> [a] -> [a]
:[Grapheme]
gs',[Grapheme]
gs'',Int
r)
where
gw :: Int
gw = Grapheme -> Int
gWidth Grapheme
g
([Grapheme]
gs',[Grapheme]
gs'',Int
r) = Int -> [Grapheme] -> ([Grapheme], [Grapheme], Int)
splitAtWidth' (Int
wInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
gw) [Grapheme]
gs
takeWidth :: Int -> [Grapheme] -> ([Grapheme],Int)
takeWidth :: Int -> [Grapheme] -> ([Grapheme], Int)
takeWidth Int
n [Grapheme]
gs = case Int -> [Grapheme] -> ([Grapheme], [Grapheme], Int)
splitAtWidth Int
n [Grapheme]
gs of
([Grapheme]
gs',[Grapheme]
_,Int
len) -> ([Grapheme]
gs',Int
len)