|
| 1 | +# Text Formatting |
| 2 | + |
| 3 | +This document describes a custom text formatting syntax used in both shell scripts and Jetpack Compose UI development. This syntax allows you to add color and style to your text output using simple tags. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The formatting system uses tags enclosed in square brackets `[]` to define styles. These tags can control text color, background color, and text attributes like bold, italic, and underline. |
| 8 | + |
| 9 | +## Supported Tags |
| 10 | + |
| 11 | +The following tags are supported: |
| 12 | + |
| 13 | +- **`[color=<value>]` / `[color]`**: |
| 14 | + |
| 15 | + - Sets the foreground color of the text. |
| 16 | + - `<value>` can be a predefined color name (see [Supported Colors](#supported-colors) below). |
| 17 | + - Using `[color]` without a value (or with an unrecognized value) typically resets the color to the default or `Color.Unspecified` in Compose. |
| 18 | + |
| 19 | +- **`[bg=<value>]` / `[bg]`**: |
| 20 | + |
| 21 | + - Sets the background color of the text. |
| 22 | + - `<value>` can be a predefined color name (see [Supported Colors](#supported-colors) below). |
| 23 | + - Using `[bg]` without a value (or with an unrecognized value) typically resets the background color to the default or `Color.Unspecified` in Compose. |
| 24 | + |
| 25 | +- **`[bold]`**: |
| 26 | + |
| 27 | + - Applies bold styling to the text. |
| 28 | + - In Compose, this sets `FontWeight.Bold`. |
| 29 | + - In the shell script, this tag is stripped if `MMRL` is not "true". To actually render bold in a terminal, you'd typically need ANSI escape codes, which this script doesn't explicitly add (it only strips the custom tags). |
| 30 | + |
| 31 | +- **`[italic]`**: |
| 32 | + |
| 33 | + - Applies italic styling to the text. |
| 34 | + - In Compose, this sets `FontStyle.Italic`. |
| 35 | + - In the shell script, this tag is stripped if `MMRL` is not "true". |
| 36 | + |
| 37 | +- **`[underline]`**: |
| 38 | + - Applies underline styling to the text. |
| 39 | + - In Compose, this sets `TextDecoration.Underline`. |
| 40 | + - In the shell script, this tag is stripped if `MMRL` is not "true". |
| 41 | + |
| 42 | +## Usage |
| 43 | + |
| 44 | +### Shell Script (`echo` function) |
| 45 | + |
| 46 | +The provided `echo` shell function processes these tags: |
| 47 | + |
| 48 | +```shell |
| 49 | +echo() { |
| 50 | + local msg="$*" |
| 51 | + if [ "$MMRL" = "true" ]; then |
| 52 | + command echo "$msg" |
| 53 | + else |
| 54 | + # Remove all custom formatting tags before printing |
| 55 | + command echo "$msg" | sed -E 's/\[(color|bg|bold|italic|underline)(=[^]]+)?]//g' |
| 56 | + fi |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +**Behavior:** |
| 61 | + |
| 62 | +- If the environment variable `MMRL` is set to `"true"`, the `echo` command will print the message as-is, including all formatting tags. This might be useful for debugging or for systems that can interpret these tags directly. |
| 63 | +- If `MMRL` is not set to `"true"` (or is set to any other value), the function strips out all custom formatting tags using `sed` before printing the message. The output will be plain text. |
| 64 | + |
| 65 | +**Example:** |
| 66 | + |
| 67 | +```shell |
| 68 | +# With MMRL not "true" (default behavior) |
| 69 | +echo "This is a [color=red]red[color] message with [bold]bold text[bold]." |
| 70 | +# Output: This is a red message with bold text. |
| 71 | + |
| 72 | +# With MMRL="true" |
| 73 | +MMRL="true" echo "This is a [color=red]red[color] message with [bold]bold text[bold]." |
| 74 | +# Output: This is a [color=red]red[color] message with [bold]bold text[bold]. |
| 75 | +``` |
| 76 | + |
| 77 | +### Jetpack Compose (`String.toStyleMarkup()`) |
| 78 | + |
| 79 | +The Kotlin extension function `toStyleMarkup()` converts a string containing these formatting tags into an `AnnotatedString`, which can be used to display styled text in Jetpack Compose. |
| 80 | + |
| 81 | +```kotlin |
| 82 | +// Simplified conceptual usage |
| 83 | +@Composable |
| 84 | +fun MyStyledText(text: String) { |
| 85 | + Text(text = text.toStyleMarkup()) |
| 86 | +} |
| 87 | + |
| 88 | +// Example |
| 89 | +MyStyledText(text = "Hello [color=blue]Blue World[color] with [bg=yellow]yellow background[bg] and [bold]bold[bold] text!") |
| 90 | +``` |
| 91 | + |
| 92 | +This will render "Hello " in the default style, "Blue World" in blue, " with " in default style, "yellow background" with a yellow background, " and " in default style, and "bold" in bold text. The styling is cumulative within the parsed segments. |
| 93 | + |
| 94 | +## Supported Colors |
| 95 | + |
| 96 | +The `colorFromName` Composable function in Kotlin defines the mapping from color names to `Color` objects. These names can be used in `[color=<name>]` and `[bg=<name>]` tags. |
| 97 | + |
| 98 | +| Color Name | Mapped To (Jetpack Compose) | |
| 99 | +| -------------------- | -------------------------------------------- | |
| 100 | +| `black` | `Color.Black` | |
| 101 | +| `red` | `Color.Red` | |
| 102 | +| `green` | `Color.Green` | |
| 103 | +| `yellow` | `Color.Yellow` | |
| 104 | +| `blue` | `Color.Blue` | |
| 105 | +| `magenta` | `Color.Magenta` | |
| 106 | +| `cyan` | `Color.Cyan` | |
| 107 | +| `white` | `Color.White` | |
| 108 | +| `gray`, `grey` | `Color.Gray` | |
| 109 | +| `lightgray` | `Color.LightGray` | |
| 110 | +| `primary` | `MaterialTheme.colorScheme.primary` | |
| 111 | +| `secondary` | `MaterialTheme.colorScheme.secondary` | |
| 112 | +| `tertiary` | `MaterialTheme.colorScheme.tertiary` | |
| 113 | +| `background` | `MaterialTheme.colorScheme.background` | |
| 114 | +| `surface` | `MaterialTheme.colorScheme.surface` | |
| 115 | +| `error` | `MaterialTheme.colorScheme.error` | |
| 116 | +| `outline` | `MaterialTheme.colorScheme.outline` | |
| 117 | +| `inverse_surface` | `MaterialTheme.colorScheme.inverseSurface` | |
| 118 | +| `inverse_on_surface` | `MaterialTheme.colorScheme.inverseOnSurface` | |
| 119 | +| `inverse_primary` | `MaterialTheme.colorScheme.inversePrimary` | |
| 120 | +| `surface_variant` | `MaterialTheme.colorScheme.surfaceVariant` | |
| 121 | +| `on_surface_variant` | `MaterialTheme.colorScheme.onSurfaceVariant` | |
| 122 | +| `surface_tint` | `MaterialTheme.colorScheme.surfaceTint` | |
| 123 | +| `on_surface` | `MaterialTheme.colorScheme.onSurface` | |
| 124 | +| `on_primary` | `MaterialTheme.colorScheme.onPrimary` | |
| 125 | +| `on_secondary` | `MaterialTheme.colorScheme.onSecondary` | |
| 126 | +| `on_tertiary` | `MaterialTheme.colorScheme.onTertiary` | |
| 127 | +| `on_background` | `MaterialTheme.colorScheme.onBackground` | |
| 128 | +| `on_error` | `MaterialTheme.colorScheme.onError` | |
| 129 | +| _(any other value)_ | `Color.Unspecified` | |
| 130 | + |
| 131 | +**Note:** Color names are case-insensitive (e.g., `Red`, `red`, `RED` are all treated the same). |
| 132 | + |
| 133 | +## Tag Nesting and Behavior |
| 134 | + |
| 135 | +In the Jetpack Compose implementation (`toStyleMarkup`): |
| 136 | + |
| 137 | +- Styles are applied segment by segment. When a tag is encountered, the style it defines (e.g., `currentColor`, `isBold`) is set and applied to subsequent text until another relevant tag changes it or the string ends. |
| 138 | +- There isn't explicit "closing" tag logic like `[/bold]`. Instead, a new tag like `[color=green]` would change the current color from whatever it was previously. For boolean styles like `bold`, `italic`, `underline`, the provided Kotlin code currently only sets them to `true`. To turn them _off_, you would need to modify the parsing logic to handle specific "off" tags (e.g., `[bold=false]`) or a general reset tag if that functionality is desired. The current parser only activates these styles. |
| 139 | + |
| 140 | +For the shell script, the `sed` command simply removes any recognized tag pattern. It does not interpret nesting or apply styles. |
0 commit comments