### Run Kotter Example Project (Bash) Source: https://github.com/varabyte/kotter/blob/main/examples/README.md These commands demonstrate how to navigate to an example directory, build the project using Gradle, and execute the compiled application. ```bash cd $demo # e.g. "cd text" ../../gradlew installDist ./build/install/$demo/bin/$demo # e.g. "./build/install/text/bin/text" ``` -------------------------------- ### Install and Run JVM Example Directly Source: https://github.com/varabyte/kotter/blob/main/README.md This snippet shows how to build and run a JVM example directly in your system terminal. It first uses `installDist` to create an executable distribution, then navigates to the `bin` directory of the installed application, and finally executes the program. This method is preferred for running examples outside of a virtual terminal. ```bash $ cd examples/life $ ../../gradlew installDist $ cd build/install/life/bin $ ./life ``` -------------------------------- ### Run JVM Example using Gradle Source: https://github.com/varabyte/kotter/blob/main/README.md This snippet demonstrates how to run a JVM example from the Kotter repository using Gradle. Navigate to the example directory and execute the `run` task. Note that this will run the example within a virtual terminal. If you need to run it directly in your system terminal, use `installDist` and then execute the binary. ```bash $ cd examples/life $ ../../gradlew run ``` -------------------------------- ### Kotlin: Manual Rerendering Example Source: https://github.com/varabyte/kotter/blob/main/README.md An example demonstrating the manual `rerender()` call within a `run` block. This approach is shown to be more fragile compared to using `LiveVar` for state management, as forgetting to call `rerender` can lead to UI inconsistencies. ```kotlin run { result = doNetworkFetchAndExpensiveCalculation() rerender() } ``` -------------------------------- ### Kotlin Widget Usage Example Source: https://github.com/varabyte/kotter/blob/main/kotterx/kotter-test-support/README.md Demonstrates how to call the `promptChoices` widget function within a `session` block. It displays a message and a list of choices, returning the user's selected option. ```kotlin session { promptChoices( "Choose a color", listOf("Red", "Orange", "Yellow", "Green", "Blue", "Purple"), ) } ``` -------------------------------- ### Kotter Test Timer with Animations and Blocking Source: https://github.com/varabyte/kotter/blob/main/kotterx/kotter-test-support/README.md Illustrates combining Kotter test timers with animations and blocking methods. This example shows advancing the timer frame by frame to match animation steps and verifying terminal output. ```kotlin val spinningAnim = textAnimOf(listOf("⠸", "⠋", "⠙", "⠸", "⠴", "⠦"), Anim.ONE_FRAME_60FPS) var testTimerReady by liveVarOf(false) section { if (!testTimerReady) return@section text(spinningAnim) text(' ') text("Calculating...") }.run { val timer = data.useTestTimer() testTimerReady = true timer.fastForward(Anim.ONE_FRAME_60FPS) blockUntilRenderMatches(terminal) { text("⠸ Calculating...") } timer.fastForward(Anim.ONE_FRAME_60FPS) blockUntilRenderMatches(terminal) { text("⠋ Calculating...") } /* ... etc. ... */ } ``` -------------------------------- ### Kotter Test Session Setup Source: https://github.com/varabyte/kotter/blob/main/kotterx/kotter-test-support/README.md Sets up a Kotter test session using the `testSession` utility. This creates an isolated, in-memory test terminal for each test, ensuring no interference between tests. The terminal is available within the lambda and is cleaned up automatically after the test completes. ```kotlin @Test fun basicKotterTestStructure() = testSession { terminal -> // Your test code goes here } ``` -------------------------------- ### Kotter Session Example in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates a basic Kotter session with interactive input and conditional output. It uses `session`, `section`, `text`, `cyan`, `textLine`, `input`, `Completions`, `liveVarOf`, and `runUntilInputEntered` to create a simple user interaction flow. The output is dynamically updated based on user input. ```kotlin session { var wantsToLearn by liveVarOf(false) section { text("Would you like to learn "); cyan { text("Kotter") }; textLine("? (Y/n)") text("> "); input(Completions("yes", "no")) if (wantsToLearn) { yellow(isBright = true) { p { textLine("\\(^_^)/\"") } } } }.runUntilInputEntered { onInputEntered { wantsToLearn = "yes".startsWith(input.lowercase()) } } } ``` -------------------------------- ### Link and Run Multiplatform Executable Source: https://github.com/varabyte/kotter/blob/main/README.md This snippet demonstrates how to build and run a multiplatform (native) executable. Unlike JVM examples, native targets do not have a virtual terminal fallback. You must link your executable using the appropriate Gradle task (e.g., `linkDebugExecutableLinuxX64`) and then run the resulting binary directly from the build output directory. Avoid using Gradle's `run` tasks for native targets. ```bash $ cd examples/native $ ../../gradlew linkDebugExecutableLinuxX64 $ ./build/bin/linuxX64/debugExecutable/native.kexe ``` -------------------------------- ### Render Styled Text Lines in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Illustrates how to use the `RenderScope` in Kotter to apply styling to text elements. This example shows how to color specific parts of a text line using extension functions like `cyan` and `textLine` to create a formatted output, such as displaying shell commands. ```kotlin section { cyan { text("cd") }; textLine(" /path/to/code") cyan { text("git") }; textLine(" init") } ``` -------------------------------- ### Manage Multiple Inputs with Unique IDs in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt This example demonstrates how to manage multiple input fields within a single section, each with a unique ID. It allows navigation between inputs using arrow keys and updates a live list of values. Dependencies include Kotter's core foundation, collections, input, and text modules. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.collections.* import com.varabyte.kotter.foundation.input.* import com.varabyte.kotter.foundation.text.* import com.varabyte.kotter.runtime.render.* fun main() = session { var selectedLine by liveVarOf(0) val colors = liveListOf(255, 128, 0) fun MainRenderScope.colorInput(line: Int, label: String) { scopedState { if (selectedLine == line) bold() text("$label: ") input( id = line, initialText = colors[line].toString(), isActive = selectedLine == line ) textLine() } } section { textLine("Enter RGB values (0-255). Use arrow keys to navigate, ESC to finish.") colorInput(0, "R") colorInput(1, "G") colorInput(2, "B") text("Result: ") rgb(colors[0], colors[1], colors[2]) { invert() textLine("COLOR PREVIEW") } }.runUntilSignal { onInputChanged { if (input.isNotBlank() && input.toIntOrNull() == null) { rejectInput() } } onInputEntered { val num = input.toIntOrNull() ?: 0 if (num in 0..255) { colors[selectedLine] = num } } onKeyPressed { when (key) { Keys.UP -> selectedLine = (selectedLine + 2) % 3 Keys.DOWN -> selectedLine = (selectedLine + 1) % 3 Keys.ESC -> signal() } } } } ``` -------------------------------- ### Input Highlighting with Custom Formatting in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt This example shows how to apply custom formatting to input characters based on their validity. In this case, digits are displayed in green, while non-digit characters are shown in red and bold. The input is rejected if it contains any non-digit characters upon submission. Dependencies include Kotter's foundation, input, and text modules. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.input.* import com.varabyte.kotter.foundation.text.* fun main() = session { section { textLine("Enter a PIN (digits only):") text("PIN: ") input( customFormat = { if (ch.isDigit()) { green() } else { red() bold() } } ) }.runUntilInputEntered { onInputEntered { if (input.any { !it.isDigit() }) { rejectInput() } } } } ``` -------------------------------- ### Execute External Commands in RunScope using Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates how to execute external processes within the `RunScope` of a Kotter application using Kotlin. The example defines a `RunScope` extension function `exec` that runs a command and waits for its completion, suitable for tasks like cloning a Git repository. ```kotlin fun RunScope.exec(vararg command: String) { val process = Runtime.getRuntime().exec(*command) process.waitFor() } section { textLine("Please wait, cloning the repo...") }.run { exec("git", "clone", "https://github.com/varabyte/kotter.git") /* ... */ } ``` -------------------------------- ### Span Both Rows and Columns in Kotter Grid Source: https://github.com/varabyte/kotter/blob/main/README.md Provides an example of a cell spanning both multiple rows and columns simultaneously within a Kotter grid, using both `rowSpan` and `colSpan` parameters. This allows for complex cell layouts. The example uses `GridCharacters.CURVED` for grid styling. ```kotlin // Spanning both grid(Cols(3, 3, 3, 3), characters = GridCharacters.CURVED) { cell(row = 1, col = 1, rowSpan = 2, colSpan = 2) cell(row = 3) // Force four rows to be created } ``` -------------------------------- ### Create Text Animations with textAnimOf Source: https://github.com/varabyte/kotter/blob/main/README.md Generate simple text animations by using the `textAnimOf` function. This function takes a list of strings (frames) and a duration, automatically starting a timer when the animation is first rendered. ```kotlin var finished = false val spinnerAnim = textAnimOf(listOf("\", "|", "/", "-"), 125.milliseconds) val thinkingAnim = textAnimOf(listOf("", ".", "..", "..."), 500.milliseconds) section { if (!finished) { text(spinnerAnim) } else { text("✓") } text(" Searching for files") if (!finished) { text(thinkingAnim) } else { text("... Done!") } }.run { doExpensiveFileSearching() finished = true } ``` -------------------------------- ### Define and Manage Custom Lifecycle with ConcurrentScopedData Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates how to define a custom lifecycle for ConcurrentScopedData and manage data associated with it. Ensures proper start and stop calls to manage data's presence within the lifecycle. ```kotlin object MyLifecycle : ConcurrentScopedData.Lifecycle private val MySetting = MyLifecycle.createKey() try { data.start(MyLifecycle) data[MySetting] = true /* ... */ } finally { data.stop(MyLifecycle) // Side effect: Removes MySetting from data } ``` -------------------------------- ### Exclude Virtual Terminal with GraalVM in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md This code snippet demonstrates how to exclude the virtual terminal when creating a session with GraalVM. This is recommended to strip out Swing code, which can be difficult to configure with GraalVM. The example uses Kotlin syntax. ```kotlin session(terminal = SystemTerminal.create()) { /* ... */ } ``` -------------------------------- ### Bash Command for Assembling and Running JVM Application Distribution Source: https://github.com/varabyte/kotter/blob/main/README.md These bash commands show how to build a distributable zip and tar archive for a JVM application using the `assembleDist` task. It then demonstrates how to extract the archive and run the application from the generated bin directory. ```bash $ cd yourkotterapp $ ./assembleDist $ cd build/distributions $ ls yourkotterapp-version.tar yourkotterapp-version.zip $ unzip yourkotterapp-version.zip $ ./yourkotterapp-version/bin/yourkotterapp ``` -------------------------------- ### Create Kotter Session with Sections (Kotlin) Source: https://context7.com/varabyte/kotter/llms.txt Demonstrates how to create a basic Kotter terminal application session and define a section to render content. Requires the kotter-foundation dependency. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.text.* fun main() = session { section { textLine("Hello, World!") }.run() } ``` -------------------------------- ### Span Multiple Rows in Kotter Grid Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates how to create a cell that spans multiple rows in a Kotter grid by utilizing the `rowSpan` parameter. This is effective for vertical cell merging. The example uses `GridCharacters.CURVED` for grid styling. ```kotlin // Spanning multiple rows grid(Cols(3, 3, 3), characters = GridCharacters.CURVED) { cell(row = 0, col = 0, rowSpan = 3) } ``` -------------------------------- ### Handle Key Presses for Interactive Applications in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt Demonstrates how to respond to specific key presses for creating interactive terminal applications. `runUntilKeyPressed` and `onKeyPressed` are used to capture keyboard input and trigger actions, such as moving an object on the screen. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.input.* import com.varabyte.kotter.foundation.text.* fun main() = session { var x by liveVarOf(10) var y by liveVarOf(5) section { textLine("Use arrow keys to move, Q to quit") textLine() for (row in 0..10) { for (col in 0..20) { if (row == y && col == x) { green { text("●") } } else { text("·") } } textLine() } }.runUntilKeyPressed(Keys.Q) { onKeyPressed { when (key) { Keys.UP -> if (y > 0) y-- Keys.DOWN -> if (y < 10) y++ Keys.LEFT -> if (x > 0) x-- Keys.RIGHT -> if (x < 20) x++ } } } } ``` -------------------------------- ### Rerender sections dynamically in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Illustrates how a `section` block can be executed multiple times. This example uses a `run` block with a variable that is updated and then triggers a `rerender` to update the UI, suitable for suspend functions and dynamic content. ```kotlin var result: Int? = null section { text("Calculating... ") if (result != null) { text("Done! Result = $result") } }.run { result = doNetworkFetchAndExpensiveCalculation() rerender() } ``` -------------------------------- ### Migrate Java Duration to Kotlin Duration Source: https://github.com/varabyte/kotter/blob/main/MIGRATING.md This example demonstrates the conversion of Java Duration objects to Kotlin's native Duration type. This change is part of Kotter's move to a multiplatform library, requiring adjustments in how time durations are handled. ```kotlin // Java Duration examples: // Duration.ofMillis(250) // Duration.ofSeconds(5) // Kotlin Duration examples: 250.milliseconds 5.seconds // Converting Java Duration to Kotlin Duration: // duration.toMillis() -> duration.inWholeMilliseconds ``` -------------------------------- ### Build Column Specifications with Kotter Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates how to construct column specifications for a Kotter grid using a builder block for fine-grained control over column sizing, including fit, fixed, and star-sized columns. The `targetWidth` parameter is used to define the total width for star-sized columns. ```kotlin grid(Cols { fit(); fixed(10); star() }, targetWidth = 80) { /* ... */ } ``` -------------------------------- ### Kotlin Session with Chained Terminal Factories Source: https://github.com/varabyte/kotter/blob/main/README.md Illustrates how to use `firstSuccess` to chain multiple terminal factory methods. This allows Kotter to attempt to initialize different terminal types in sequence, falling back to a virtual terminal if the primary system terminal is unavailable. It also shows how to customize the virtual terminal with a title and size. ```kotlin session( terminal = listOf( { SystemTerminal() }, { VirtualTerminal.create(title = "My App", terminalSize = Dimension(30, 30)) }, ).firstSuccess() ) { /* ... */ } ``` -------------------------------- ### Span Multiple Columns in Kotter Grid Source: https://github.com/varabyte/kotter/blob/main/README.md Shows how to make a cell in a Kotter grid span across multiple columns using the `colSpan` parameter. This is useful for creating headers or merging cells horizontally. The example uses `GridCharacters.CURVED` for grid styling. ```kotlin // Spanning multiple columns grid(Cols(3, 3, 3), characters = GridCharacters.CURVED) { cell(row = 0, col = 0, colSpan = 3) cell(row = 2) // Force three rows to be created } ``` -------------------------------- ### Manage state within sections in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Explains that state changes within a `section` block are localized to that block. This prevents unexpected bugs by ensuring effects do not persist outside their intended scope. Includes examples of default color rendering after a scoped section. ```kotlin section { blue(BG) red() text("This text is red on blue") }.run() section { text("This text is rendered using default colors") }.run() ``` -------------------------------- ### Intercept and Modify User Input in Kotter Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates intercepting and modifying user input in real-time within a Kotter application using the `onInputChanged` event. The example shows converting input to uppercase. The `input` variable within the block holds the current user input. ```kotlin section { text("Please enter your name: "); input() }.run { onInputChanged { input = input.toUpperCase() } /* ... */ } ``` -------------------------------- ### Styling Text and Colors in Kotter (Kotlin) Source: https://context7.com/varabyte/kotter/llms.txt Shows how to apply various text styles, ANSI colors, and decorations within a Kotter terminal session. Supports nested styling and RGB/HSV colors. Requires kotter-foundation and kotter-foundation-text dependencies. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.text.* import com.varabyte.kotter.foundation.text.ColorLayer.* fun main() = session { section { // Nested scoped colors red { text("Red text") } text(" ") blue { text("Blue text") } textLine() // Background colors white(BG) { black { textLine("Black on white") } } // Text decorations bold { text("Bold") } text(" ") underline { text("Underlined") } text(" ") strikethrough { textLine("Strikethrough") } // RGB colors (if terminal supports truecolor) rgb(0xFF5500) { textLine("Custom orange color") } hsv(240, 1.0f, 1.0f) { textLine("Pure blue via HSV") } // Combined effects scopedState { bold() red() blue(BG) underline() textLine("Bold, underlined red on blue") } }.run() } ``` -------------------------------- ### Validate and Reject User Input in Kotter Source: https://github.com/varabyte/kotter/blob/main/README.md Shows how to validate user input and reject invalid entries in Kotter using the `rejectInput()` method within the `onInputChanged` event. This example ensures that only letters are accepted as input, reverting to the previous valid state if invalid characters are typed. ```kotlin section { text("Please enter your name: "); input() }.run { onInputChanged { if (input.any { !it.isLetter() }) { rejectInput() } // Would also work: input = input.filter { it.isLetter() } // although often `rejectInput()` specifies your intention more clearly } /* ... */ } ``` -------------------------------- ### Create Render Animations with Full Control in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt Shows how to create animations with complete rendering control, allowing access to colors and effects. `renderAnimOf` is used to define animations where each frame can generate custom text, colors, and styles. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.anim.* import com.varabyte.kotter.foundation.text.* import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds fun main() = session { val rainbowAnim = renderAnimOf(360, 50.milliseconds) { frame -> val hue = frame % 360 hsv(hue, 1.0f, 1.0f) } val progressAnim = renderAnimOf(20, 100.milliseconds, looping = false) { frame -> text("[") text("█".repeat(frame)) text("░".repeat(20 - frame)) text("]") } section { rainbowAnim(this) textLine("RAINBOW TEXT") progressAnim(this) textLine() }.run { delay(2.seconds) } } ``` -------------------------------- ### Grid Layout System in Kotlin for UI Design Source: https://context7.com/varabyte/kotter/llms.txt Implements a flexible grid layout system for creating multi-column UIs with automatic sizing and borders. Supports fixed, fitting, and star-sized columns, as well as cell spanning. The `grid` function takes column definitions and a set of cells to render. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.text.* import com.varabyte.kotterx.grid.* fun main() = session { section { // Fixed width columns grid(Cols(10, 15, 20), characters = GridCharacters.CURVED) { cell { textLine("Col 1") } cell { textLine("Column 2") } cell { textLine("Third Column") } cell { textLine("Row 2-1") } cell { textLine("Row 2-2") } cell { textLine("Row 2-3") } } textLine() // Fit, fixed, and star-sized columns grid( Cols { fit() // Size to content fixed(10) // Fixed 10 chars star() // Take remaining space }, targetWidth = 60, characters = GridCharacters.CURVED ) { cell { text("Name") } cell { text("Age") } cell { text("Email") } cell { text("Alice") } cell { text("30") } cell { text("alice@example.com") } cell { text("Bob") } cell { text("25") } cell { text("bob@example.com") } } textLine() // Cell spanning grid(Cols(10, 10, 10), characters = GridCharacters.CURVED) { cell(colSpan = 3) { textLine("Header spans all columns") } cell { text("A") } cell { text("B") } cell { text("C") } } }.run() } ``` -------------------------------- ### Configure Kotlin Multiplatform Project Source: https://github.com/varabyte/kotter/blob/main/README.md This snippet configures a Kotlin Multiplatform project in `build.gradle.kts`. It specifies targets for Linux, Windows, and macOS, defines the entry point for executables, and sets up dependencies for common main and test sources. Ensure you have the necessary build tools for each target platform. ```kotlin plugins { kotlin("multiplatform") } repositories { mavenCentral() } kotlin { // Choose the targets you care about. // Note: You will need the right machine to build each one; otherwise, the target is disabled automatically listOf( linuxX64(), // Linux mingwX64(), // Windows macosArm64(), // Mac M1 macosX64() // Mac Legacy ).forEach { nativeTarget -> nativeTarget.apply { binaries { executable { entryPoint = "main" } } } } sourceSets { val commonMain by getting { dependencies { implementation("com.varabyte.kotter:kotter:1.2.1") } } val commonTest by getting { dependencies { implementation("com.varabyte.kotterx:kotter-test-support:1.2.1") } } } } ``` -------------------------------- ### Kotlin Fallback Logic for Non-Interactive Terminals Source: https://github.com/varabyte/kotter/blob/main/README.md This Kotlin code demonstrates how to implement a fallback mechanism for Kotter applications. It attempts to run the main logic within a Kotter session and catches exceptions. If the exception occurs before Kotter starts, it executes fallback logic; otherwise, it re-throws the exception. ```kotlin private fun Session.runKotterLogic() { /* ... */ } private fun runFallbackLogic() { /* ... */ } fun main() { var kotterStarted = false try { session { kotterStarted = true runKotterLogic() } } catch (ex: Exception) { if (!kotterStarted) { runFallbackLogic() } else { // This exception came from after startup, when the user was // interacting with Kotter. Crashing with an informative stack // is probably the best thing we can do at this point. throw ex } } } ``` -------------------------------- ### User Input Handling and Auto-Completion in Kotter (Kotlin) Source: https://context7.com/varabyte/kotter/llms.txt Demonstrates capturing user input with features like auto-completion suggestions and input validation. Handles input lifecycle events like changing and completion. Requires kotter-foundation, kotter-foundation-text, and kotter-foundation-input dependencies. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.input.* import com.varabyte.kotter.foundation.text.* fun main() = session { var name = "" var wantsToLearn by liveVarOf(false) // Simple input with completions section { text("Would you like to learn Kotter? (Y/n) ") input(Completions("yes", "no")) if (wantsToLearn) { yellow(isBright = true) { textLine() textLine("Great choice!") } } }.runUntilInputEntered { onInputEntered { wantsToLearn = "yes".startsWith(input.lowercase()) } } // Input with validation section { text("Enter your name (letters only): ") input() }.runUntilInputEntered { onInputChanged { if (input.any { !it.isLetter() }) { rejectInput() } } onInputEntered { name = input } } section { textLine("Hello, $name!") }.run() } ``` -------------------------------- ### Implement Input Suggestions with InputCompleter Source: https://github.com/varabyte/kotter/blob/main/README.md Allows users to receive suggestions based on their current input by implementing the `InputCompleter` interface. The `complete` method should return the suggestion or null if none is found. The suggestion should only be the text that follows the user's input so far. ```kotlin interface InputCompleter { fun complete(input: String): String? } input(object : InputCompleter { override fun complete(input: String): String? { /* ... */ } }) ``` ```kotlin object : InputCompleter { override fun complete(input: String): String? { return names .firstOrNull { it.startsWith(input) } ?.let { it.drop(input.length) } // NOTE: ^^^^^^^^^^^^^^^^^^^^ // Don't return the whole word; just the part that comes after the user's input so far. } } ``` -------------------------------- ### Handle Choice Selection Logic in Kotlin Source: https://github.com/varabyte/kotter/blob/main/kotterx/kotter-test-support/README.md Handles user input for selecting choices using arrow keys or digit keys. This method should be called within a `runUntilSignal` block and emits a signal upon confirmed selection. It takes functions to get and set the selected index, and the maximum number of choices. ```kotlin internal fun RunScope.handleChoiceSelection( getSelectedIndex: () -> Int, maxIndex: Int, setSelectedIndex: (Int) -> Unit, ) { onKeyPressed { when (key) { Keys.UP -> setSelectedIndex((getSelectedIndex() - 1).coerceAtLeast(0)) Keys.DOWN -> setSelectedIndex((getSelectedIndex() + 1).coerceAtMost(maxIndex - 1)) Keys.ENTER -> signal() Keys.DIGIT_1, Keys.DIGIT_2, Keys.DIGIT_3, Keys.DIGIT_4, Keys.DIGIT_5, Keys.DIGIT_6, Keys.DIGIT_7, Keys.DIGIT_8, Keys.DIGIT_9 -> { val digit = (key as CharKey).code.digitToInt() val index = digit - 1 if (index < maxIndex) { setSelectedIndex(index) signal() } } } } } ``` -------------------------------- ### Create Looping and One-Shot Text Animations in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt Demonstrates how to create text animations that loop or run once, updating automatically. It uses `textAnimOf` to define the animation frames and their durations. The animations can be integrated into a `session` for display. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.anim.* import com.varabyte.kotter.foundation.text.* import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds fun main() = session { var isComplete by liveVarOf(false) val spinnerAnim = textAnimOf( listOf("⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"), 80.milliseconds ) val dotsAnim = textAnimOf( listOf("", ".", "..", "..."), 500.milliseconds ) section { if (!isComplete) { text(spinnerAnim) text(" Loading") text(dotsAnim) } else { green { text("✓") } textLine(" Complete!") } }.run { delay(5.seconds) isComplete = true } } ``` -------------------------------- ### Kotlin: Reactive Collections with LiveList Source: https://github.com/varabyte/kotter/blob/main/README.md Illustrates how to use LiveList for reactive collections that automatically rerender when items are added or removed. Initialize with `liveListOf` within a `session` block. Use `withWriteLock` for modifications involving multiple operations to prevent race conditions. ```kotlin val fileWalker = FileWalker(".") // This class doesn't exist but just pretend for this example... val fileMatches = liveListOf() section { textLine("Matches found so far:") if (fileMatches.isNotEmpty()) { for (match in fileMatches) { textLine(" - $match") } } else { textLine("No matches so far...") } }.run { fileWalker.findFiles("*.txt") { file -> fileMatches += file.name } } ``` ```kotlin val fileWalker = FileWalker(".") val last10Matches = liveListOf() section { /* ... */ }.run { fileWalker.findFiles("*.txt") { file -> last10Matches.withWriteLock { add(file.name) if (size > 10) { removeAt(0) } } } } ``` -------------------------------- ### Reactive Collections with LiveList in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt This snippet demonstrates the use of `liveListOf` to create a reactive list. Changes to the list (adding elements) automatically trigger UI rerenders. The user can enter numbers, and pressing ENTER on an empty line signals the end of input, after which the sum of the entered numbers is displayed. Dependencies include Kotter's foundation, collections, input, and text modules. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.collections.* import com.varabyte.kotter.foundation.input.* import com.varabyte.kotter.foundation.text.* fun main() = session { val numbers = liveListOf() var isDone by liveVarOf(false) section { if (!isDone) { textLine("Enter numbers (press ENTER on empty line to finish):") numbers.forEach { num -> textLine(" $num") } text("+ "); input() } else { textLine("Numbers entered:") numbers.forEachIndexed { i, num -> text(if (i < numbers.lastIndex) " " else "+ ") textLine("$num") } textLine("-".repeat(20)) textLine(" Sum: ${numbers.sum()}") } }.runUntilSignal { onInputChanged { if (input.isNotBlank() && input.toIntOrNull() == null) { rejectInput() } } onInputEntered { if (input.isEmpty()) { isDone = true signal() } else { numbers.add(input.toInt()) clearInput() } } } } ``` -------------------------------- ### Implement a One-Shot Wipe-Right Animation (Kotlin) Source: https://github.com/varabyte/kotter/blob/main/README.md Illustrates the creation of a one-shot render animation that simulates a wipe-right effect. The `looping` parameter is set to `false`, and the animation is run until its total duration has passed to ensure completion. ```kotlin val arrow = "=============>" val wipeRightAnim = renderAnimOf( arrow.length + 1, // `length + 1` because empty string is also a frame 40.milliseconds, looping = false ) { frameIndex -> textLine(arrow.take(frameIndex)) } section { text("Go this way: "); wipeRightAnim(this) }.runUntilSignal { // Give the animation time to complete: addTimer(wipeRightAnim.totalDuration) { signal() } } ``` -------------------------------- ### Kotlin Session with Sequential Sections Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates the basic usage of Kotter's session and section blocks, where sections are executed sequentially on a single render thread. The `run` block executes on the calling thread, ensuring progress is made only after its logic completes. This pattern is designed to prevent rendering conflicts and clobbered text. ```kotlin session { section { /* ... render thread ... */ }.run { /* ... current thread ... */ } section { /* ... render thread ... */ }.run { /* ... current thread ... */ } section { /* ... render thread ... */ }.run { /* ... current thread ... */ } } ``` -------------------------------- ### Send Keys with sendKeys in Kotlin Source: https://github.com/varabyte/kotter/blob/main/kotterx/kotter-test-support/README.md The `sendKeys` method simulates user input by sending raw ASCII values representing keys to be typed. This is the lowest-level method for input simulation, with `sendKey` available for single key presses. It is typically used within `runUntilInputEntered` to ensure all input is processed. ```kotlin section { input() }.runUntilInputEntered { // Send the ASCII values for "Hello, world!" terminal.sendKeys( 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33 ) terminal.sendKey(13) // ASCII code for the enter key } terminal.assertMatches { text("Hello, world! ") // "input" includes a trailing space for the cursor } ``` -------------------------------- ### Use Aside Blocks for Static Output in Kotlin Source: https://context7.com/varabyte/kotter/llms.txt Explains how to use 'aside' blocks to generate static output that persists while an active section is dynamically updated. This is useful for maintaining a history or log alongside changing content in the terminal. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.render.* import com.varabyte.kotter.foundation.text.* import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.milliseconds fun main() = session { var processed by liveVarOf(0) var isComplete by liveVarOf(false) section { if (!isComplete) { textLine("Processing files...") } else { green { textLine("✓ All files processed!") } } }.run { aside { textLine("Files processed:") textLine() } val files = listOf("config.json", "data.csv", "image.png", "doc.pdf") files.forEachIndexed { index, file -> delay(500.milliseconds) aside { textLine(" [$index/$index] $file") } processed++ } isComplete = true } } ``` -------------------------------- ### Create clickable links in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Shows how to define clickable hyperlinks within the text output. This feature is not guaranteed to work on all terminals and may render as normal text if unsupported. ```kotlin section { text("Would you like to ") link("https://github.com/varabyte/kotter", "learn Kotter") textLine("?") } ``` -------------------------------- ### Create Reusable Text Animation Templates Source: https://github.com/varabyte/kotter/blob/main/README.md Define reusable animation patterns using `TextAnim.Template`. Instances can then be created from these templates, allowing for consistent animations across different parts of your application. ```kotlin val SPINNER_TEMPATE = TextAnim.Template(listOf("\", "|", "/", "-"), 250.milliseconds) val spinners = (1..10).map { textAnimOf(SPINNER_TEMPLATE) } /* ... */ ``` -------------------------------- ### Basic Kotter Text Output Source: https://github.com/varabyte/kotter/blob/main/README.md This snippet shows the most basic usage of Kotter to print text to the console, equivalent to `println("Hello, World")`. It utilizes a `session` to establish the application's scope and a `section` to define a block of text to be rendered. The `run()` method on the section triggers the output and blocks until rendering is complete. ```kotlin session { section { textLine("Hello, World") }.run() } ``` -------------------------------- ### Apply text colors directly in Kotlin Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates applying foreground and background colors directly using color methods. Colors remain active until the next color method is called. Supports specifying the layer (FG or BG) or defaulting to FG. ```kotlin section { green(layer = BG) red() // defaults to FG layer if no layer specified textLine("Red on green") blue() textLine("Blue on green") }.run() ``` -------------------------------- ### Create a Two-Column Grid in Kotter Source: https://github.com/varabyte/kotter/blob/main/README.md Demonstrates creating a grid with two columns in Kotlin using Kotter. Rows are automatically added as cells are declared. Each column has a specified width, and characters for borders can be customized. ```kotlin section { // A grid with two columns, each with space for 6 characters grid(Cols(6, 6), characters = GridCharacters.CURVED) { cell { // Auto set to row=0, col=0 textLine("Cell1") } cell { // Auto set to row=0, col=1 textLine("Cell2") } // Third cell in a grid with two columns creates a new row cell { // Auto set to row=1, col=0 textLine("Cell3") } cell { // Auto set to row=1, col=1 textLine("Cell4") } // You can explicitly set the row and column if you want. Rows and columns // are 0-indexed. cell(row = 2, col = 1) { // Jump over cell row=2,col=0 textLine("Cell6") } } }.run() ``` -------------------------------- ### Reactive State Management with LiveVar in Kotter (Kotlin) Source: https://context7.com/varabyte/kotter/llms.txt Illustrates using Kotter's LiveVar for reactive state management, where UI automatically rerenders when variable values change. Requires kotter-foundation, kotter-foundation-text, and kotlinx.coroutines dependencies. ```kotlin import com.varabyte.kotter.foundation.* import com.varabyte.kotter.foundation.text.* import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.milliseconds fun main() = session { var count by liveVarOf(0) var progress by liveVarOf(0) section { textLine("Count: $count") text("Progress: [") text("=".repeat(progress)) text("-".repeat(10 - progress)) textLine("]") }.run { for (i in 0..10) { delay(100.milliseconds) count = i progress = i } } } ``` -------------------------------- ### Kotlin Session with Virtual Terminal Creation Source: https://github.com/varabyte/kotter/blob/main/README.md Shows how to explicitly configure Kotter to use a virtual terminal. This is useful for ensuring interactive terminal behavior even in environments where a system terminal might not be available or fully supported, such as IDE debuggers or when running via Gradle. ```kotlin session(terminal = VirtualTerminal.create()) { section { /* ... */ } /* ... */ } ```