Files
Vellum/app/src/main/java/space/bloggin/vellum/Markup.kt
T

72 lines
2.4 KiB
Kotlin

package space.bloggin.vellum
/**
* Verse markup: {words|H430} Strong's group, [words] translator italics, <words> words of Jesus.
*/
object Markup {
data class Seg(val text: String, val jesus: Boolean, val italic: Boolean, val strong: String?)
fun parse(s: String): List<Seg> {
val out = ArrayList<Seg>()
var jesus = false
var italic = false
val buf = StringBuilder()
fun flush(strong: String? = null) {
if (buf.isNotEmpty()) {
out.add(Seg(buf.toString(), jesus, italic, strong)); buf.clear()
}
}
var i = 0
while (i < s.length) {
when (val ch = s[i]) {
'<' -> { flush(); jesus = true }
'>' -> { flush(); jesus = false }
'[' -> { flush(); italic = true }
']' -> { flush(); italic = false }
'{' -> {
flush()
val bar = s.indexOf('|', i)
val close = s.indexOf('}', i)
if (bar in (i + 1) until close) {
// the word itself may contain [ ] italics in rare cases; strip them
val word = s.substring(i + 1, bar)
val num = s.substring(bar + 1, close)
out.add(Seg(word, jesus, italic, num))
i = close
} else buf.append(ch)
}
else -> buf.append(ch)
}
i++
}
flush()
return out
}
fun plain(s: String): String {
if (s.none { it == '{' || it == '[' || it == '<' }) return s
val sb = StringBuilder(s.length)
var i = 0
while (i < s.length) {
val ch = s[i]
when (ch) {
'<', '>', '[', ']' -> {}
'{' -> {
val bar = s.indexOf('|', i)
val close = s.indexOf('}', i)
if (bar in (i + 1) until close) {
sb.append(s, i + 1, bar); i = close
} else sb.append(ch)
}
else -> sb.append(ch)
}
i++
}
return sb.toString()
}
/** Strong's-tagged words in a verse, in order, deduplicated by number+word. */
fun words(s: String): List<Pair<String, String>> =
parse(s).filter { it.strong != null }.map { it.text to it.strong!! }.distinct()
}