package be.simplenotes.domain.utils import be.simplenotes.search.SearchTerms import java.util.* private enum class Quote { SingleQuote, DoubleQuote, } private data class ParsedSearchInput(val global: List, val entries: Map) private fun parseInput(input: String): ParsedSearchInput { val tokenizer = StringTokenizer(input, ":\"' ", true) val tokens = ArrayList() val current = StringBuilder() var quoteOpen: Quote? = null fun push() { if (current.isNotEmpty()) { tokens.add(current.toString()) } current.setLength(0) quoteOpen = null } while (tokenizer.hasMoreTokens()) { when (val token = tokenizer.nextToken()) { "\"" -> when { Quote.DoubleQuote == quoteOpen -> push() quoteOpen == null -> quoteOpen = Quote.DoubleQuote else -> current.append(token) } "'" -> when { Quote.SingleQuote == quoteOpen -> push() quoteOpen == null -> quoteOpen = Quote.SingleQuote else -> current.append(token) } " " -> { if (quoteOpen != null) current.append(" ") else push() } ":" -> { push() tokens.add(token) } else -> { current.append(token) } } } push() val entries = HashMap() val colonIndexes = ArrayList() tokens.forEachIndexed { index, token -> if (token == ":") colonIndexes += index } var changes = 0 for (colonIndex in colonIndexes) { val offset = changes * 3 val key = tokens.getOrNull(colonIndex - 1 - offset) val value = tokens.getOrNull(colonIndex + 1 - offset) if (key != null && value != null) { entries[key] = value tokens.removeAt(colonIndex - 1 - offset) // remove key tokens.removeAt(colonIndex - 1 - offset) // remove : tokens.removeAt(colonIndex - 1 - offset) // remove value changes++ } } return ParsedSearchInput(global = tokens, entries = entries) } internal fun parseSearchTerms(input: String): SearchTerms { val parsedInput = parseInput(input) val title: String? = parsedInput.entries["title"] val tag: String? = parsedInput.entries["tag"] val content: String? = parsedInput.entries["content"] val all = parsedInput.global.takeIf { it.isNotEmpty() }?.joinToString(" ") return SearchTerms( title = title, tag = tag, content = content, all = all ) }