terminal colors, multi-line strings; bump to 0.8

This commit is contained in:
alex-s168
2024-03-28 22:44:15 +01:00
parent bd60bf5b27
commit e8d4fb16b1
9 changed files with 230 additions and 34 deletions

View File

@@ -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")

View File

@@ -5,7 +5,7 @@ plugins {
}
group = "me.alex_s168"
version = "0.7"
version = "0.8"
repositories {
mavenCentral()

View File

@@ -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) }

View File

@@ -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)
}

View 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")
}

View 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)
}

View 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"

View 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
View 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)
}
}