diff src/main/kotlin/name/blackcap/passman/See.kt @ 3:eafa3779aef8

More bug fixes, quote strings in diagnostics.
author David Barts <n5jrn@me.com>
date Sun, 11 Sep 2022 20:36:06 -0700
parents a6cfdffcaa94
children 02b101422726
line wrap: on
line diff
--- a/src/main/kotlin/name/blackcap/passman/See.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/See.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -1,56 +1,46 @@
 package name.blackcap.passman
 
+/* Would be nice if there was a more programmatic and comprehensive way of
+   doing this, but alas. Even the oft-recommended StringEscapeUtils does
+   something cruder than the below. Le sigh. */
+
 import java.util.Formatter
 
-private val UNPRINTABLE = setOf<Character.UnicodeBlock>(
-    Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS,
-    Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS_EXTENDED,
-    Character.UnicodeBlock.COMBINING_HALF_MARKS,
-    Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS_SUPPLEMENT,
-    Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS,
-    Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES,
-    Character.UnicodeBlock.HIGH_SURROGATES,
-    Character.UnicodeBlock.LOW_SURROGATES,
-    Character.UnicodeBlock.PRIVATE_USE_AREA,
-    Character.UnicodeBlock.SPECIALS,
+private const val DELIM = '"'
 
-)
+private val STD_ESC_MAP = mapOf<Char, Char>('\t' to 't', '\b' to 'b', '\n' to 'n',
+    '\r' to 'r', '\u000c' to 'f', '\"' to '"', '\\' to '\\')
+private const val MIN_ASCII = ' '
+private const val MAX_ASCII = '~'
+private const val MIN_8859 = '\u00a1'
+private const val MAX_8859 = '\u00ff'
+private const val SHY = '\u00ad'
 
-private val DELIM = '"'
+fun see(input: String, simple: Boolean = false): String =
+    if (simple) seeSimple(input) else seeAggressive(input)
 
-private val EXEMPT = setOf<Char>(' ')
-private val PREFIXED = setOf<Char>(DELIM, '\\')
+private fun seeSimple(input: String): String = StringBuilder().run {
+    append(DELIM)
+    append(input)
+    append(DELIM)
+    toString()
+}
 
-fun see(input: String): String {
-    val accum = StringBuilder()
-    val formatter = Formatter(accum)
-    accum.append(DELIM)
+private fun seeAggressive(input: String): String {
+    val accum = Formatter()
+    accum.format("%c", DELIM)
     for (ch in input) {
-        val block = Character.UnicodeBlock.of(ch)
-        if (ch in EXEMPT) {
-            accum.append(ch)
-        } else if (block == null || block in UNPRINTABLE || Character.isSpaceChar(ch) || Character.isWhitespace(ch)) {
-            formatter.format("\\u%04x", ch.code)
-        } else if (ch in PREFIXED) {
-            accum.append('\\')
-            accum.append(ch)
+        if ((ch in MIN_ASCII..MAX_ASCII) || ((ch != SHY) && (ch in MIN_8859 .. MAX_8859))) {
+            accum.format("%c", ch)
+            continue
+        }
+        val mapped = STD_ESC_MAP[ch]
+        if (mapped != null) {
+            accum.format("\\%c", mapped)
         } else {
-            accum.append(ch)
+            accum.format("\\u%04x", ch.code)
         }
     }
-    accum.append(DELIM)
+    accum.format("%c", DELIM)
     return accum.toString()
 }
-
-fun dump(input: String): String {
-    val accum = StringBuilder()
-    var needSpace = false
-    for (ch in input) {
-        if (needSpace) {
-            accum.append(' ')
-        }
-        accum.append(ch.code)
-        needSpace = true
-    }
-    return accum.toString()
-}