Created
April 4, 2017 09:42
-
-
Save grandstaish/89a073194885b53228d120e561ca4df2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun Node.format(): String { | |
return formatInternal().lines.joinToString(separator = "\n") | |
} | |
fun max(a: Int, b: Int, c: Int): Int { | |
return Math.max(Math.max(a, b), c) | |
} | |
fun String.center(width: Int, fillChar: Char = ' ') : String { | |
var s = this | |
var left = true | |
while (s.length < width) { | |
if (left) { | |
s = fillChar + s | |
} else { | |
s += fillChar | |
} | |
left = !left | |
} | |
return s | |
} | |
fun Node.formatInternal() : FormatParts { | |
var label = value.toString() | |
val (leftLines, leftPos, leftWidth) = left?.formatInternal() ?: FormatParts(mutableListOf(), 0, 0) | |
val (rightLines, rightPos, rightWidth) = right?.formatInternal() ?: FormatParts(mutableListOf(), 0, 0) | |
// Ensure left and right lines are the same size by appending whitespace. | |
while (leftLines.size < rightLines.size) { | |
leftLines.add(" ".repeat(leftWidth)) | |
} | |
while (rightLines.size < leftLines.size) { | |
rightLines.add(" ".repeat(rightWidth)) | |
} | |
val middle = max(rightPos + leftWidth - leftPos + 1, label.length, 2) | |
val pos = leftPos + (middle / 2) | |
val width = leftPos + middle + rightWidth - rightPos | |
val lines = mutableListOf<String>() | |
// Pad the label with '.'s to match middle length | |
if ((middle - label.length) % 2 == 1 | |
&& parent != null | |
&& this != parent.left | |
&& label.length < middle) { | |
label += '.' | |
} | |
label = label.center(middle, '.') | |
if (label[0] == '.') { | |
label = ' ' + label.substring(1) | |
} | |
if (label[label.length - 1] == '.') { | |
label = label.substring(0, label.length - 1) + ' ' | |
} | |
// Add the value | |
var valueLine = "" | |
valueLine += " ".repeat(leftPos) | |
valueLine += label | |
valueLine += " ".repeat(rightWidth - rightPos) | |
lines.add(valueLine) | |
// Add arrows when children exist. | |
var slashLine = "" | |
slashLine += " ".repeat(leftPos) | |
slashLine += if (left != null) "/" else " " | |
slashLine += " ".repeat(middle - 2) | |
slashLine += if (right != null) "\\" else " " | |
slashLine += " ".repeat(rightWidth - rightPos) | |
lines.add(slashLine) | |
// Add rest of the lines from the left and right children | |
(0 until leftLines.size).mapTo(lines) { | |
var result = leftLines[it] | |
result += " ".repeat(width - leftWidth - rightWidth) | |
result += rightLines[it] | |
result | |
} | |
return FormatParts(lines, pos, width) | |
} | |
data class FormatParts(val lines: MutableList<String>, val pos: Int, val width: Int) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Draws something that looks like this: