Skip to content

Commit 41860c0

Browse files
committed
add new text formatting api
1 parent 84cf491 commit 41860c0

2 files changed

Lines changed: 141 additions & 0 deletions

File tree

docs/.vitepress/config/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ function sidebarGuide() {
9797
{ text: "What is MMRL", link: "/guide/" },
9898
{ text: "How a Module Card Works", link: "/guide/how-a-module-card-works" },
9999
{ text: "Anti-Features", link: "/guide/antifeatures" },
100+
{ text: "Text Formatting", link: "/guide/text-formatting" },
100101
{ text: "Installer API", link: "/guide/installer" },
101102
{ text: "FAQ", link: "/guide/faq" },
102103
],

docs/en/guide/text-formatting.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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

Comments
 (0)