on develop help sign in
Merge branch 'charwidthfix' of github.com:pdlla/reflex-vty into aa/ci-macos
7ee1170Ali Abrar
reflex-vty.cabal+1−2
@@ -40,14 +40,13 @@ library
40 data-default >= 0.7.1 && < 0.8,
40 data-default >= 0.7.1 && < 0.8,
41 dependent-map >= 0.4 && < 0.5,
41 dependent-map >= 0.4 && < 0.5,
42 text >= 1.2.3 && < 1.3,
42 text >= 1.2.3 && < 1.3,
43− text-icu >= 0.7 && < 0.8,
44 dependent-sum >= 0.7 && < 0.8,
43 dependent-sum >= 0.7 && < 0.8,
45 exception-transformers >= 0.4.0 && < 0.5,
44 exception-transformers >= 0.4.0 && < 0.5,
46 primitive >= 0.6.3 && < 0.8,
45 primitive >= 0.6.3 && < 0.8,
47 ref-tf >= 0.4.0 && < 0.5,
46 ref-tf >= 0.4.0 && < 0.5,
48 reflex >= 0.7.2 && < 0.8,
47 reflex >= 0.7.2 && < 0.8,
49 time >= 1.8.0 && < 1.10,
48 time >= 1.8.0 && < 1.10,
50− vty >= 5.21 && < 5.29
49+ vty >= 5.28 && < 5.29
51 hs-source-dirs: src
50 hs-source-dirs: src
52 default-language: Haskell2010
51 default-language: Haskell2010
53 ghc-options: -Wall
52 ghc-options: -Wall
src/Data/Text/Zipper.hs+26−10
@@ -22,12 +22,13 @@ import Control.Monad.State (evalState, forM, get, put)
22
22
23import Data.Text (Text)
23import Data.Text (Text)
24import qualified Data.Text as T
24import qualified Data.Text as T
25−import Data.Text.ICU.Char
26import Data.Text.Internal (Text(..), text)
25import Data.Text.Internal (Text(..), text)
27import Data.Text.Internal.Fusion (stream)
26import Data.Text.Internal.Fusion (stream)
28import Data.Text.Internal.Fusion.Types (Stream(..), Step(..))
27import Data.Text.Internal.Fusion.Types (Stream(..), Step(..))
29import Data.Text.Unsafe
28import Data.Text.Unsafe
30
29
30+import Graphics.Text.Width (wcwidth)
31+
31-- | A zipper of the logical text input contents (the "document"). The lines
32-- | A zipper of the logical text input contents (the "document"). The lines
32-- before the line containing the cursor are stored in reverse order.
33-- before the line containing the cursor are stored in reverse order.
33-- The cursor is logically between the "before" and "after" text.
34-- The cursor is logically between the "before" and "after" text.
@@ -331,12 +332,13 @@ dropWidth n = snd . splitAtWidth n
331
332
332-- | Get the display width of a 'Char'. "Full width" and "wide" characters
333-- | Get the display width of a 'Char'. "Full width" and "wide" characters
333-- take two columns and everything else takes a single column. See
334-- take two columns and everything else takes a single column. See
334−-- <https://www.unicode.org/reports/tr11/> for more information.
335+-- <https://www.unicode.org/reports/tr11/> for more information
336+-- This is implemented using wcwidth from Vty such that it matches what will
337+-- be displayed on the terminal. Note that this method can change depending
338+-- on how vty is configed. Please see vty documentation for details.
335charWidth :: Char -> Int
339charWidth :: Char -> Int
336−charWidth c = case property EastAsianWidth c of
340+charWidth = wcwidth
337− EAFull -> 2
341+
338− EAWide -> 2
339− _ -> 1
340
342
341-- | For a given set of wrapped logical lines, computes a map
343-- | For a given set of wrapped logical lines, computes a map
342-- from display line index to text offset in the original text.
344-- from display line index to text offset in the original text.
@@ -380,10 +382,12 @@ goToDisplayLinePosition x y dl tz =
380 in case offset of
382 in case offset of
381 Nothing -> tz
383 Nothing -> tz
382 Just o ->
384 Just o ->
385+ let
383− let displayLineLength = case drop y $ _displayLines_spans dl of
386+ moveRight = case drop y $ _displayLines_spans dl of
384− [] -> x
387+ [] -> x
385− (s:_) -> spansWidth s
388+ (s:_) -> charIndexAt x . stream . mconcat . fmap (\(Span _ t) -> t) $ s
386− in rightN (o + min displayLineLength x) $ top tz
389+ in rightN (o + min moveRight x) $ top tz
390+
387
391
388-- | Get the width of the text in a set of 'Span's, taking into account unicode character widths
392-- | Get the width of the text in a set of 'Span's, taking into account unicode character widths
389spansWidth :: [Span tag] -> Int
393spansWidth :: [Span tag] -> Int
@@ -408,3 +412,15 @@ widthI (Stream next s0 _len) = loop_length 0 s0
408 Skip s' -> loop_length z s'
412 Skip s' -> loop_length z s'
409 Yield c s' -> loop_length (z + charWidth c) s'
413 Yield c s' -> loop_length (z + charWidth c) s'
410{-# INLINE[0] widthI #-}
414{-# INLINE[0] widthI #-}
415+
416+-- | Compute the logical index position of a stream of characters from a visual
417+-- position taking into account fullwidth unicode forms.
418+charIndexAt :: Int -> Stream Char -> Int
419+charIndexAt pos (Stream next s0 _len) = loop_length 0 0 s0
420+ where
421+ loop_length i !z s = case next s of
422+ Done -> i
423+ Skip s' -> loop_length i z s'
424+ Yield c s' -> if w > pos then i else loop_length (i+1) w s' where
425+ w = z + charWidth c
426+{-# INLINE[0] charIndexAt #-}