Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,23 @@ import org.jetbrains.compose.resources.plural.PluralCategory
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi

private val SimpleStringFormatRegex = Regex("""%(\d+)\$[ds]""")
internal fun String.replaceWithArgs(args: List<String>) = SimpleStringFormatRegex.replace(this) { matchResult ->
args[matchResult.groupValues[1].toInt() - 1]
private val SimpleStringFormatRegex = Regex("""%(?:([1-9]\d*)\$)?[ds]""")
internal fun String.replaceWithArgs(args: List<String>): String {
if (!SimpleStringFormatRegex.containsMatchIn(this)) return this

return SimpleStringFormatRegex.replace(this) { match ->
val placeholderNumber = match.groups[1]?.value?.toIntOrNull()
val index = when {
placeholderNumber != null -> placeholderNumber - 1
args.size == 1 -> 0
else -> {
throw IllegalArgumentException(
"Formatting failed: Non-positional placeholder '${match.value}' is ambiguous when multiple arguments are provided in \"$this\""
)
}
}
args[index]
}
}

internal sealed interface StringItem {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,44 @@ class StringFormatTest {
// Only the first argument should be used, ignoring the rest
assertEquals("Hello Alice!", result)
}
}

@Test
fun `replaceWithArgs handle single argument format`() {
val template = "Hello %s!"
val args = listOf("Alice")

val result = template.replaceWithArgs(args)

assertEquals("Hello Alice!", result)
}

@Test
fun `replaceWithArgs handle multiple placeholders for single argument`() {
val template = "%s and %s are best friends!"
val args = listOf("Alice")

val result = template.replaceWithArgs(args)

assertEquals("Alice and Alice are best friends!", result)
}

@Test
fun `replaceWithArgs throw exception when multiple different arguments with single placeholder format`() {
val template = "Hello %s, you have %d new messages!"
val args = listOf("Alice", "15")

assertFailsWith<IllegalArgumentException> {
template.replaceWithArgs(args)
}
}

@Test
fun `replaceWithArgs throw exception when mixing single and multiple placeholders format`() {
val template = "Hello %1\$s, you have %s new messages!"
val args = listOf("Alice", "15")

assertFailsWith<IllegalArgumentException> {
template.replaceWithArgs(args)
}
}
}