ansiform-0.7.8.5: src/Ansiform/Internal/Width.hs
-- | Terminal display width for characters and strings.
module Ansiform.Internal.Width (charWidth, textWidth) where
--------------------------------------------------------------------------------
import Data.Char (GeneralCategory (..), generalCategory, ord)
-- Display Width
--------------------------------------------------------------------------------
-- | Number of terminal columns occupied by a character.
-- Combining marks and other zero width characters return zero,
-- East Asian wide characters and emoji return two.
charWidth :: Char -> Int
charWidth c
| isZeroWidth c = 0
| isWide c = 2
| otherwise = 1
-- | Number of terminal columns occupied by a string.
textWidth :: String -> Int
textWidth = sum . fmap charWidth
-- Support Functions
--------------------------------------------------------------------------------
-- Checks for characters that do not advance the cursor.
isZeroWidth :: Char -> Bool
isZeroWidth c = case generalCategory c of
NonSpacingMark -> True
EnclosingMark -> True
Format -> True
_ -> inRange 0x1160 0x11FF c -- Hangul Jamo vowels and finals.
|| inRange 0x200B 0x200B c -- Zero width space.
|| inRange 0x1F3FB 0x1F3FF c -- Emoji skin tone modifiers.
-- Checks for characters that occupy two columns.
isWide :: Char -> Bool
isWide c = any (\(lo,hi) -> inRange lo hi c) wideRanges
inRange :: Int -> Int -> Char -> Bool
inRange lo hi c = lo <= ord c && ord c <= hi
-- East Asian wide and fullwidth ranges, plus the main emoji blocks.
wideRanges :: [(Int, Int)]
wideRanges =
[ (0x1100, 0x115F) -- Hangul Jamo initials.
, (0x2329, 0x232A) -- Angle brackets.
, (0x2E80, 0x303E) -- CJK radicals, Kangxi and CJK symbols.
, (0x3041, 0x33FF) -- Kana, Bopomofo, Jamo and compatibility.
, (0x3400, 0x4DBF) -- CJK extension A.
, (0x4E00, 0x9FFF) -- CJK unified ideographs.
, (0xA000, 0xA4CF) -- Yi syllables.
, (0xA960, 0xA97F) -- Hangul Jamo extended A.
, (0xAC00, 0xD7A3) -- Hangul syllables.
, (0xF900, 0xFAFF) -- CJK compatibility ideographs.
, (0xFE10, 0xFE19) -- Vertical forms.
, (0xFE30, 0xFE6F) -- CJK compatibility forms.
, (0xFF00, 0xFF60) -- Fullwidth forms.
, (0xFFE0, 0xFFE6) -- Fullwidth signs.
, (0x1F004, 0x1F004) -- Mahjong red dragon.
, (0x1F0CF, 0x1F0CF) -- Playing card joker.
, (0x1F18E, 0x1F18E) -- Squared AB.
, (0x1F191, 0x1F19A) -- Squared symbols.
, (0x1F200, 0x1F2FF) -- Enclosed ideographic supplement.
, (0x1F300, 0x1F64F) -- Pictographs and emoticons.
, (0x1F680, 0x1F6FF) -- Transport and map symbols.
, (0x1F780, 0x1F7FF) -- Geometric shapes extended.
, (0x1F900, 0x1F9FF) -- Supplemental pictographs.
, (0x1FA70, 0x1FAFF) -- Pictographs extended A.
, (0x20000, 0x2FFFD) -- CJK extensions B to F.
, (0x30000, 0x3FFFD) -- CJK extensions G and later.
]