-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathWCWidth.hs
71 lines (57 loc) · 2.09 KB
/
WCWidth.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
{-# LANGUAGE ForeignFunctionInterface #-}
{-| A binding for the native 'wcwidth'. It's important that you 'setLocale'
before using it, like this:
> #!/usr/bin/env runhaskell
>
> import Text.Printf
>
> import System.Locale.SetLocale
> import Data.Char.WCWidth
>
> main = do
> setLocale LC_ALL (Just "")
> sequence_ [ display c | c <- chars ]
> where
> chars = [minBound..'A']
> display c = printf "%04x %2d %s\n" (fromEnum c) (wcwidth c) (show c)
The program file @WCWidthTableaux.hs@ contains a more extensive example of
using 'wcwidth'.
Note that this binding to the native implementation gets certain
characters wrong in obvious ways as well as ways that are problematic for
indentation based languages. The ASCII tab should be assigned a width of
8, not -1; and one is likely to find -1 assigned to numerous obscure
characters (for example, symbols from the Book of Changes).
-}
module Data.Char.WCWidth
( wcwidth
, widths
, ranges
) where
import Foreign.C
import Data.List
import qualified Data.Char.WCWidth.Internal.Haskell as WCH
{-| Widths of all characters.
-}
widths :: [ (Char, Int) ]
widths = [ (c, wcwidth c) | c <- [minBound..maxBound] ]
{-| Characters broken into contiguous ranges with the same width.
-}
ranges :: [ ((Char, Char), Int) ]
ranges = reverse (foldl' aggregate start (tail widths))
where
start = aggregate [] (head widths)
aggregate [] (c, w) = [((c, c), w)]
aggregate (((a, z), i) : t) (c, w)
| i == w = ((a, c), i) : t
| otherwise = ((c, c), w) : ((a, z), i) : t
{-| Binding to the native 'wcwidth'.
-}
wcwidth :: Char -> Int
#if defined(mingw32_HOST_OS)
wcwidth = WCH.wcwidth
#else
wcwidth = fromEnum . native . toEnum . fromEnum
#endif
#if !defined(mingw32_HOST_OS)
foreign import ccall unsafe "wchar.h wcwidth" native :: CWchar -> CInt
#endif