
Parses CSI/SGR ANSI escape sequences into styled text slices with color, intensity and style metadata; reconstructs plain text, iterates lines, and supports all 16 ANSI colors.
A Kotlin Multiplatform Native library for parsing and categorising ANSI escape codes. This is a port of the Rust cansi crate.
Categorise ANSI - ANSI escape code parser and categoriser
cansi-kotlin parses text with ANSI escape sequences and returns deconstructed text with
metadata about coloring and styling. The library focuses on CSI (Control Sequence Introducer)
sequences, particularly SGR (Select Graphic Rendition) parameters.
This library is not yet published to Maven Central. The recommended approach is to include it as a git submodule or vendored dependency:
git submodule add https://github.com/KotlinMania/cansi-kotlin.gitThen in your settings.gradle.kts:
include(":cansi-kotlin")And in your module's build.gradle.kts:
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":cansi-kotlin"))
}
}
}
}import cansi.*
// Parse text with ANSI escape sequences
val text = "\u001b[31mHello\u001b[0m, \u001b[32mWorld\u001b[0m!"
val slices = categoriseText(text)
// Each slice contains the text and its styling
for (slice in slices) {
println("Text: '${slice.text}', Color: ${slice.fg}")
}
// Output:
// Text: 'Hello', Color: Red
// Text: ', ', Color: null
// Text: 'World', Color: Green
// Text: '!', Color: null
// Reconstruct the plain text without escape codes
val plainText = constructTextNoCodes(slices)
println(plainText) // "Hello, World!"parse(text) - Find all ANSI escape sequences and return their positionscategoriseText(text) - Parse text and return styled slices with color/formatting infoconstructTextNoCodes(slices) - Reconstruct plain text from categorized sliceslineIter(slices) - Iterate over slices line by lineCategorisedSlice - A text slice with styling information (colors, bold, italic, etc.)Color - The 16 standard ANSI colors (8 normal + 8 bright variants)Intensity - Text intensity (Normal, Bold, Faint)Match - An ANSI escape sequence match with byte positionsimport cansi.*
val styledText = "\u001b[1;31;4mError:\u001b[0m Something went wrong"
val slices = categoriseText(styledText)
// First slice: "Error:" with bold, red, underline
val errorSlice = slices[0]
println("Text: ${errorSlice.text}") // "Error:"
println("Bold: ${errorSlice.intensity}") // Bold
println("Color: ${errorSlice.fg}") // Red
println("Underline: ${errorSlice.underline}") // true
// Second slice: " Something went wrong" with default styling
val msgSlice = slices[1]
println("Text: ${msgSlice.text}") // " Something went wrong"
println("Color: ${msgSlice.fg}") // null (default)Licensed under either of:
at your option.
This Kotlin Multiplatform port was created by Sydney Renee of The Solace Project for KotlinMania.
Special thanks to the original author:
A Kotlin Multiplatform Native library for parsing and categorising ANSI escape codes. This is a port of the Rust cansi crate.
Categorise ANSI - ANSI escape code parser and categoriser
cansi-kotlin parses text with ANSI escape sequences and returns deconstructed text with
metadata about coloring and styling. The library focuses on CSI (Control Sequence Introducer)
sequences, particularly SGR (Select Graphic Rendition) parameters.
This library is not yet published to Maven Central. The recommended approach is to include it as a git submodule or vendored dependency:
git submodule add https://github.com/KotlinMania/cansi-kotlin.gitThen in your settings.gradle.kts:
include(":cansi-kotlin")And in your module's build.gradle.kts:
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":cansi-kotlin"))
}
}
}
}import cansi.*
// Parse text with ANSI escape sequences
val text = "\u001b[31mHello\u001b[0m, \u001b[32mWorld\u001b[0m!"
val slices = categoriseText(text)
// Each slice contains the text and its styling
for (slice in slices) {
println("Text: '${slice.text}', Color: ${slice.fg}")
}
// Output:
// Text: 'Hello', Color: Red
// Text: ', ', Color: null
// Text: 'World', Color: Green
// Text: '!', Color: null
// Reconstruct the plain text without escape codes
val plainText = constructTextNoCodes(slices)
println(plainText) // "Hello, World!"parse(text) - Find all ANSI escape sequences and return their positionscategoriseText(text) - Parse text and return styled slices with color/formatting infoconstructTextNoCodes(slices) - Reconstruct plain text from categorized sliceslineIter(slices) - Iterate over slices line by lineCategorisedSlice - A text slice with styling information (colors, bold, italic, etc.)Color - The 16 standard ANSI colors (8 normal + 8 bright variants)Intensity - Text intensity (Normal, Bold, Faint)Match - An ANSI escape sequence match with byte positionsimport cansi.*
val styledText = "\u001b[1;31;4mError:\u001b[0m Something went wrong"
val slices = categoriseText(styledText)
// First slice: "Error:" with bold, red, underline
val errorSlice = slices[0]
println("Text: ${errorSlice.text}") // "Error:"
println("Bold: ${errorSlice.intensity}") // Bold
println("Color: ${errorSlice.fg}") // Red
println("Underline: ${errorSlice.underline}") // true
// Second slice: " Something went wrong" with default styling
val msgSlice = slices[1]
println("Text: ${msgSlice.text}") // " Something went wrong"
println("Color: ${msgSlice.fg}") // null (default)Licensed under either of:
at your option.
This Kotlin Multiplatform port was created by Sydney Renee of The Solace Project for KotlinMania.
Special thanks to the original author: