terminal colors, multi-line strings; bump to 0.8
This commit is contained in:
@@ -25,6 +25,11 @@ val fib = lazySequence(0 to 1) { i, f ->
|
||||
|
||||
println(fib[10])
|
||||
```
|
||||
### Terminal colors
|
||||
```kotlin
|
||||
Terminal.print("Hello, ", Terminal.STYLES.BOLD)
|
||||
Terminal.println("World!", Terminal.COLORS.RED.brighter.fg, Terminal.COLORS.WHITE.bg)
|
||||
```
|
||||
### Unix `uniq`
|
||||
```kotlin
|
||||
val inp = sequenceOf("AAA", "BBB", "AAA", "AAA", "AAA", "BBB")
|
||||
|
@@ -5,7 +5,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "me.alex_s168"
|
||||
version = "0.7"
|
||||
version = "0.8"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@@ -1,33 +0,0 @@
|
||||
package blitz
|
||||
|
||||
import blitz.collections.contents
|
||||
import blitz.collections.easyMappingSequence
|
||||
import blitz.func.*
|
||||
import blitz.func.io.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
// pureCat(args)
|
||||
// .impure()
|
||||
|
||||
val inp = sequenceOf("AAA", "BBB", "AAA", "AAA", "AAA", "BBB")
|
||||
val out = inp.easyMappingSequence { i, s, m ->
|
||||
if (s(i-1) == m(i)) null
|
||||
else m(i)
|
||||
}
|
||||
println(out.contents)
|
||||
}
|
||||
|
||||
// `cat` command
|
||||
fun pureCat(args: Array<String>): Monad<Unit> =
|
||||
args
|
||||
.ifEmpty { arrayOf("-") }
|
||||
.map {
|
||||
if (it == "-") readIn()
|
||||
else unit(it)
|
||||
.asPath()
|
||||
.read()
|
||||
.stringify()
|
||||
}
|
||||
.rewrap()
|
||||
.flatten()
|
||||
.reduce { s -> print(s) }
|
@@ -1,5 +1,13 @@
|
||||
package blitz
|
||||
|
||||
@Deprecated(
|
||||
level = DeprecationLevel.ERROR,
|
||||
message = "Will be removed in the future!",
|
||||
replaceWith = ReplaceWith(
|
||||
"Terminal.warn",
|
||||
"blitz.term.Terminal"
|
||||
)
|
||||
)
|
||||
fun warn(msg: String) {
|
||||
System.err.println(msg)
|
||||
}
|
53
src/main/kotlin/blitz/str/MutMultiLineString.kt
Normal file
53
src/main/kotlin/blitz/str/MutMultiLineString.kt
Normal file
@@ -0,0 +1,53 @@
|
||||
package blitz.str
|
||||
|
||||
class MutMultiLineString(
|
||||
var fill: Char
|
||||
) {
|
||||
val lines = mutableListOf<MutString>()
|
||||
|
||||
// TODO: wrap at \n
|
||||
|
||||
/** if out of bounds, extends with @see fill */
|
||||
operator fun get(row: Int, col: Int): Char {
|
||||
if (row >= lines.size) {
|
||||
repeat(row - lines.size + 1) {
|
||||
lines.add(MutString(fill = fill))
|
||||
}
|
||||
}
|
||||
return lines[row][col]
|
||||
}
|
||||
|
||||
/** if out of bounds, extends with @see fill */
|
||||
operator fun set(row: Int, col: Int, value: Char) {
|
||||
if (row >= lines.size) {
|
||||
repeat(row - lines.size + 1) {
|
||||
lines.add(MutString(fill = fill))
|
||||
}
|
||||
} else {
|
||||
lines[row].fill = fill
|
||||
}
|
||||
lines[row][col] = value
|
||||
}
|
||||
|
||||
/** if out of bounds, extends with @see fill */
|
||||
operator fun set(row: Int, colStart: Int, value: CharSequence) {
|
||||
if (row >= lines.size) {
|
||||
repeat(row - lines.size + 1) {
|
||||
lines.add(MutString(fill = fill))
|
||||
}
|
||||
} else {
|
||||
lines[row].fill = fill
|
||||
}
|
||||
lines[row][colStart] = value
|
||||
}
|
||||
|
||||
/** if out of bounds, extends with @see fill */
|
||||
operator fun set(rowStart: Int, colStart: Int, value: MutMultiLineString) {
|
||||
value.lines.forEachIndexed { index, line ->
|
||||
this[index + rowStart, colStart] = line
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
lines.joinToString(separator = "\n")
|
||||
}
|
61
src/main/kotlin/blitz/str/MutString.kt
Normal file
61
src/main/kotlin/blitz/str/MutString.kt
Normal file
@@ -0,0 +1,61 @@
|
||||
package blitz.str
|
||||
|
||||
class MutString(
|
||||
init: String = "",
|
||||
var fill: Char
|
||||
): CharSequence, Appendable {
|
||||
private val builder = StringBuilder(init)
|
||||
|
||||
override val length: Int
|
||||
get() = builder.length
|
||||
|
||||
override operator fun get(index: Int): Char {
|
||||
if (index >= length) {
|
||||
repeat(index - length + 1) {
|
||||
builder.append(fill)
|
||||
}
|
||||
}
|
||||
return builder[index]
|
||||
}
|
||||
|
||||
/** if out of bounds, extends with @see fill */
|
||||
operator fun set(index: Int, value: Char) {
|
||||
if (index >= length) {
|
||||
repeat(index - length + 1) {
|
||||
builder.append(fill)
|
||||
}
|
||||
}
|
||||
builder[index] = value
|
||||
}
|
||||
|
||||
/** if out of bounds, extends with @see fill */
|
||||
operator fun set(start: Int, str: CharSequence) {
|
||||
if (start >= length) {
|
||||
repeat(start - length + 1) {
|
||||
builder.append(fill)
|
||||
}
|
||||
}
|
||||
builder.insert(start, str)
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
builder.toString()
|
||||
|
||||
override fun append(csq: CharSequence?): Appendable {
|
||||
builder.append(csq)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun append(csq: CharSequence?, start: Int, end: Int): Appendable {
|
||||
builder.append(csq, start, end)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun append(c: Char): Appendable {
|
||||
builder.append(c)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence =
|
||||
builder.subSequence(startIndex, endIndex)
|
||||
}
|
16
src/main/kotlin/blitz/term/AnsiiStr.kt
Normal file
16
src/main/kotlin/blitz/term/AnsiiStr.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
package blitz.term
|
||||
|
||||
class AnsiiMode(internal val values: MutableList<Int>) {
|
||||
constructor(mo: Int): this(mutableListOf(mo))
|
||||
|
||||
operator fun plus(other: AnsiiMode): AnsiiMode =
|
||||
AnsiiMode((values + other.values).toMutableList())
|
||||
}
|
||||
|
||||
private val escape = (27).toChar()
|
||||
|
||||
fun ansiiStr(str: String, vararg modes: AnsiiMode) =
|
||||
if (modes.isEmpty())
|
||||
str
|
||||
else
|
||||
"$escape[${modes.flatMap { it.values }.joinToString(separator = ";")}m$str$escape[0m"
|
70
src/main/kotlin/blitz/term/Terminal.kt
Normal file
70
src/main/kotlin/blitz/term/Terminal.kt
Normal file
@@ -0,0 +1,70 @@
|
||||
package blitz.term
|
||||
|
||||
object Terminal {
|
||||
object COLORS {
|
||||
val BLACK = Color(AnsiiMode(30), AnsiiMode(40))
|
||||
val RED = Color(AnsiiMode(31), AnsiiMode(41))
|
||||
val GREEN = Color(AnsiiMode(32), AnsiiMode(42))
|
||||
val YELLOW = Color(AnsiiMode(33), AnsiiMode(43))
|
||||
val BLUE = Color(AnsiiMode(34), AnsiiMode(44))
|
||||
val MAGENTA = Color(AnsiiMode(35), AnsiiMode(45))
|
||||
val CYAN = Color(AnsiiMode(36), AnsiiMode(46))
|
||||
val WHITE = Color(AnsiiMode(37), AnsiiMode(47))
|
||||
}
|
||||
|
||||
object STYLES {
|
||||
val BOLD = AnsiiMode(1)
|
||||
val DIM = AnsiiMode(2)
|
||||
val UNDERLINE = AnsiiMode(4)
|
||||
val BLINK = AnsiiMode(5)
|
||||
}
|
||||
|
||||
class Color(
|
||||
val fg: AnsiiMode,
|
||||
val bg: AnsiiMode,
|
||||
brighterIn: Color? = null,
|
||||
darkerIn: Color? = null
|
||||
) {
|
||||
private fun ch(mode: AnsiiMode): Int =
|
||||
mode.values[0]
|
||||
|
||||
private fun brighterChannel(va: Int): Int =
|
||||
if (va <= 50) va + 60 else va
|
||||
|
||||
private fun darkerChannel(va: Int): Int =
|
||||
if (va >= 50) va - 60 else va
|
||||
|
||||
val brighter by lazy { Color(AnsiiMode(brighterChannel(ch(fg))), AnsiiMode(brighterChannel(ch(bg)))) }
|
||||
val darker by lazy { Color(AnsiiMode(darkerChannel(ch(fg))), AnsiiMode(darkerChannel(ch(bg)))) }
|
||||
}
|
||||
|
||||
fun encodeString(str: String, vararg modes: AnsiiMode) =
|
||||
ansiiStr(str, *modes)
|
||||
|
||||
fun print(str: String, vararg modes: AnsiiMode) {
|
||||
kotlin.io.print(encodeString(str, *modes))
|
||||
}
|
||||
|
||||
fun println(str: String, vararg modes: AnsiiMode) {
|
||||
kotlin.io.println(encodeString(str, *modes))
|
||||
}
|
||||
|
||||
fun err(str: String, vararg modes: AnsiiMode) {
|
||||
System.err.print(encodeString(str, *modes))
|
||||
}
|
||||
|
||||
fun errln(str: String, vararg modes: AnsiiMode) {
|
||||
System.err.println(encodeString(str, *modes))
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Use errln instead!",
|
||||
ReplaceWith(
|
||||
"errln(str, *modes)",
|
||||
"blitz.term.Terminal.errln"
|
||||
)
|
||||
)
|
||||
fun warn(str: String, vararg modes: AnsiiMode) {
|
||||
errln(str, *modes)
|
||||
}
|
||||
}
|
16
src/test/kotlin/uniq.kt
Normal file
16
src/test/kotlin/uniq.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
import blitz.collections.contents
|
||||
import blitz.collections.easyMappingSequence
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class GeneratorSequences {
|
||||
@Test
|
||||
fun uniq() {
|
||||
val inp = sequenceOf("AAA", "BBB", "AAA", "AAA", "AAA", "BBB")
|
||||
val out = inp.easyMappingSequence { i, s, m ->
|
||||
if (s(i-1) == m(i)) null
|
||||
else m(i)
|
||||
}.filterNotNull()
|
||||
assertEquals(out.contents, listOf("AAA", "BBB", "AAA", "BBB").contents)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user