Skip to content

Commit a6d5fb9

Browse files
committed
Add Segmenter
Resolves #4
1 parent bd8e64b commit a6d5fb9

File tree

4 files changed

+196
-1
lines changed

4 files changed

+196
-1
lines changed

spago.dhall

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
, "maybe"
88
, "nullable"
99
, "prelude"
10+
, "tuples"
11+
, "unfoldable"
1012
, "unsafe-coerce"
1113
]
1214
, packages = ./packages.dhall

src/Web/Intl/Segmenter.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"use strict";
2+
3+
export function _new(locales, options) {
4+
return new Intl.Segmenter(locales, options);
5+
}
6+
7+
export function _resolvedOptions(segmenter) {
8+
return segmenter.resolvedOptions();
9+
}
10+
11+
export function _segment(segmenter, string) {
12+
return segmenter.segment(string)[Symbol.iterator]();
13+
}
14+
15+
export function _supportedLocalesOf(locales, options) {
16+
return Intl.Segmenter.supportedLocalesOf(locales, options);
17+
}
18+
19+
export function _nextSegment(nothing, just, tuple, segments) {
20+
const next = segments.next();
21+
if (next.done) {
22+
return nothing;
23+
}
24+
return just(tuple(next.value, segments));
25+
}

src/Web/Intl/Segmenter.purs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
module Web.Intl.Segmenter
2+
-- * Types
3+
( Segmenter
4+
, SegmenterOptions
5+
6+
-- * Constructor
7+
, new
8+
, new_
9+
10+
-- * Methods
11+
, resolvedOptions
12+
, supportedLocalesOf
13+
, supportedLocalesOf_
14+
, segment
15+
) where
16+
17+
import Data.Array.NonEmpty (NonEmptyArray)
18+
import Data.Array.NonEmpty as NonEmpty
19+
import Data.Function.Uncurried (Fn2, Fn4)
20+
import Data.Function.Uncurried as Function.Uncurried
21+
import Data.Maybe (Maybe(..))
22+
import Data.Tuple (Tuple(..))
23+
import Data.Unfoldable (class Unfoldable)
24+
import Data.Unfoldable as Unfoldable
25+
import Effect (Effect)
26+
import Effect.Uncurried (EffectFn1, EffectFn2)
27+
import Effect.Uncurried as Effect.Uncurried
28+
import Prim.Row (class Union)
29+
import Unsafe.Coerce as Unsafe.Coerce
30+
import Web.Intl.Locale (Locale)
31+
32+
foreign import data Segmenter :: Type
33+
34+
type SegmenterOptions =
35+
( localeMatcher :: String
36+
, granularity :: String
37+
)
38+
39+
foreign import _new
40+
:: EffectFn2
41+
(Array Locale)
42+
(Record SegmenterOptions)
43+
Segmenter
44+
45+
new
46+
:: forall options options'
47+
. Union options options' SegmenterOptions
48+
=> NonEmptyArray Locale
49+
-> Record options
50+
-> Effect Segmenter
51+
new locales options =
52+
Effect.Uncurried.runEffectFn2 _new (NonEmpty.toArray locales) (Unsafe.Coerce.unsafeCoerce options)
53+
54+
new_ :: NonEmptyArray Locale -> Effect Segmenter
55+
new_ locales =
56+
new locales {}
57+
58+
foreign import _supportedLocalesOf
59+
:: Fn2
60+
(Array Locale)
61+
(Record SegmenterOptions)
62+
(Array String)
63+
64+
supportedLocalesOf
65+
:: forall options options'
66+
. Union options options' SegmenterOptions
67+
=> NonEmptyArray Locale
68+
-> Record options
69+
-> Array String
70+
supportedLocalesOf locales options =
71+
Function.Uncurried.runFn2 _supportedLocalesOf (NonEmpty.toArray locales) (Unsafe.Coerce.unsafeCoerce options)
72+
73+
supportedLocalesOf_
74+
:: NonEmptyArray Locale
75+
-> Array String
76+
supportedLocalesOf_ locales =
77+
supportedLocalesOf locales {}
78+
79+
type Segment =
80+
{ segment :: String
81+
, isWordLike :: Boolean
82+
, input :: String
83+
, index :: Int
84+
}
85+
86+
foreign import data Segments :: Type
87+
88+
foreign import _segment
89+
:: Fn2
90+
Segmenter
91+
String
92+
Segments
93+
94+
foreign import _nextSegment
95+
:: Fn4
96+
(forall a. Maybe a)
97+
(forall a. a -> (Maybe a))
98+
(forall a b. Fn2 a b (Tuple a b))
99+
Segments
100+
(Maybe (Tuple Segment Segments))
101+
102+
segment
103+
:: forall f
104+
. Unfoldable f
105+
=> Segmenter
106+
-> String
107+
-> f Segment
108+
segment segmenter string =
109+
Unfoldable.unfoldr
110+
(Function.Uncurried.runFn4 _nextSegment Nothing Just (Function.Uncurried.mkFn2 Tuple))
111+
(Function.Uncurried.runFn2 _segment segmenter string)
112+
113+
type ResolvedOptions =
114+
{ locale :: String
115+
, granularity :: String
116+
}
117+
118+
foreign import _resolvedOptions
119+
:: EffectFn1
120+
Segmenter
121+
ResolvedOptions
122+
123+
resolvedOptions
124+
:: Segmenter
125+
-> Effect ResolvedOptions
126+
resolvedOptions = Effect.Uncurried.runEffectFn1 _resolvedOptions

test/Main.purs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import Web.Intl.NumberFormat as NumberFormat
2323
import Web.Intl.PluralRules as PluralRules
2424
import Web.Intl.RelativeTimeFormat as RelativeTimeFormat
2525
import Web.Intl.RelativeTimeUnit (RelativeTimeUnit(..))
26+
import Web.Intl.Segmenter as Segmenter
2627

2728
main :: Effect Unit
2829
main = do
@@ -36,6 +37,7 @@ main = do
3637
test_NumberFormat
3738
test_PluralRules
3839
test_RelativeTimeFormat
40+
test_Segmenter
3941

4042
test_Intl :: Effect Unit
4143
test_Intl = do
@@ -502,4 +504,44 @@ test_RelativeTimeFormat = do
502504
, numeric: "auto"
503505
, style: "long"
504506
}
505-
}
507+
}
508+
509+
test_Segmenter :: Effect Unit
510+
test_Segmenter = do
511+
en_US <- NonEmpty.singleton <$> Locale.new_ "en-US"
512+
513+
Console.log "Segmenter.supportedLocalesOf"
514+
Test.assertEqual
515+
{ actual: Segmenter.supportedLocalesOf en_US { localeMatcher: "best fit" }
516+
, expected: [ "en-US" ]
517+
}
518+
519+
Console.log "Segmenter.supportedLocalesOf_"
520+
Test.assertEqual
521+
{ actual: Segmenter.supportedLocalesOf_ en_US
522+
, expected: [ "en-US" ]
523+
}
524+
525+
segmenter <- Segmenter.new en_US { granularity: "word" }
526+
527+
Console.log "Segmenter.segment"
528+
Test.assertEqual
529+
{ actual: _.segment <$> Segmenter.segment segmenter "Hello, world!"
530+
, expected:
531+
[ "Hello"
532+
, ","
533+
, " "
534+
, "world"
535+
, "!"
536+
]
537+
}
538+
539+
Console.log "Segmenter.resolvedOptions"
540+
resolvedOptions <- Segmenter.resolvedOptions segmenter
541+
Test.assertEqual
542+
{ actual: resolvedOptions
543+
, expected:
544+
{ locale: "en-US"
545+
, granularity: "word"
546+
}
547+
}

0 commit comments

Comments
 (0)