-
Notifications
You must be signed in to change notification settings - Fork 0
/
TextMatcher.kt
94 lines (81 loc) · 3.03 KB
/
TextMatcher.kt
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package sh.calvin.autolinktext
import androidx.compose.runtime.Composable
interface TextMatcherDefaultsInterface {
@NotForAndroid
fun webUrl(contextData: ContextData): TextMatcher<Any?> =
TextMatcher.RegexMatcher(BackUpRegex.WebUrl, MatchFilterDefaults.WebUrls)
@NotForAndroid
fun emailAddress(contextData: ContextData): TextMatcher<Any?> =
TextMatcher.RegexMatcher(BackUpRegex.Email)
@NotForAndroid
fun phoneNumber(contextData: ContextData): TextMatcher<Any?> =
TextMatcher.RegexMatcher(BackUpRegex.PhoneNumber, MatchFilterDefaults.PhoneNumber)
@OptIn(NotForAndroid::class)
@Composable
fun webUrl() = webUrl(NullContextData)
@OptIn(NotForAndroid::class)
@Composable
fun emailAddress() = emailAddress(NullContextData)
@OptIn(NotForAndroid::class)
@Composable
fun phoneNumber() = phoneNumber(NullContextData)
}
internal expect fun getMatcherDefaults(): TextMatcherDefaultsInterface
val TextMatcherDefaults = getMatcherDefaults()
/**
* A [TextMatcher] is used to match text in a string.
*/
sealed class TextMatcher<out T> {
abstract fun apply(text: String): List<SimpleTextMatchResult<T>>
/**
* A [TextMatcher] that matches a [Regex] in the text.
*/
class RegexMatcher(
val regex: Regex,
val matchFilter: MatchFilter<MatchResult> = MatchFilterDefaults.NoOp,
) : TextMatcher<MatchResult>() {
override fun apply(text: String): List<SimpleTextMatchResult<MatchResult>> {
val matches = mutableListOf<SimpleTextMatchResult<MatchResult>>()
regex.findAll(text).forEach {
val result = SimpleTextMatchResult(
start = it.range.first,
endExclusive = it.range.last + 1,
it
)
if (matchFilter(text, result)) {
matches.add(result)
}
}
return matches
}
}
/**
* A [TextMatcher] that matches all instances of a string in the text.
*/
class StringMatcher(
val string: String,
val matchFilter: MatchFilter<Nothing?> = MatchFilterDefaults.NoOp,
) : TextMatcher<Nothing?>() {
override fun apply(text: String): List<SimpleTextMatchResult<Nothing?>> {
val matches = mutableListOf<SimpleTextMatchResult<Nothing?>>()
var index = text.indexOf(string)
while (index != -1) {
val result = SimpleTextMatchResult(index, index + string.length)
if (matchFilter(text, result)) {
matches.add(result)
}
index = text.indexOf(string, index + 1)
}
return matches
}
}
/**
* A [TextMatcher] that matches based on a function.
*/
class FunctionMatcher<out T>(val function: (String) -> List<SimpleTextMatchResult<T>>) :
TextMatcher<T>() {
override fun apply(text: String): List<SimpleTextMatchResult<T>> {
return function(text)
}
}
}