Skip to content

Commit 602f071

Browse files
ADFA-4436 Add RainbowOnTheGo plugin (depth-colored brackets) (#32)
* ADFA-4436 Add RainbowOnTheGo plugin (depth-colored brackets) A plugin that colors matching parentheses, brackets, and braces by nesting depth. It implements the generic EditorDecorationProvider API: its decorate() method scans a region of editor text for brackets, tracks nesting depth, skips brackets inside strings/comments, and returns six-color day/night spans. The Code On The Go editor merges those spans on top of normal highlighting — all of the rainbow logic lives in the plugin; the IDE knows nothing about brackets. Mirrors the random-xkcd template: build.gradle.kts/settings.gradle.kts, AndroidManifest plugin.* metadata, DocumentationExtension tooltip + Tier-3 in-IDE help, and a top-level documentation HTML. Adds an Examples table row. No UI, no permissions, no network. Requires a Code On The Go build that includes the EditorDecorationProvider API (IDE-side support in ADFA-4436). * ADFA-4436 Wire rainbow-on-the-go into website deploy and set min IDE version - Add rainbow-on-the-go to the deploy MAP in update-libs.yml so its .cgp ships to the plugins website (auto-discovered by build-plugins.yml). - Set plugin.min_ide_version to 26.27 (when the new plugin API ships). - Correct CLAUDE.md: new plugins only need the update-libs.yml MAP; build-plugins.yml auto-discovers. * ADFA-4436 Fix rainbow lexer, gate to Java/Kotlin, cache prefix state - Collapse the prefix-recovery and emitting scans into one shared lexer so they can't diverge; apply the newline reset uniformly (a // comment or string no longer suppresses coloring for the rest of a multi-line region). - Restrict coloring to Java/Kotlin via FileOpenExtension (observe-only; canHandleFileOpen=false). Gate defaults off, so other languages are never colored. Drop the #-as-comment rule (wrong for Java/Kotlin). - Add a per-document checkpoint cache so decorate() resumes prefix lexing from the nearest cached offset instead of rescanning [0,start) every call, turning sequential decoration from ~O(N^2) into ~O(N). - Update manifest/docs to say Java/Kotlin only and reflect file-open observation (reads no file contents).
1 parent be36d69 commit 602f071

21 files changed

Lines changed: 1166 additions & 1 deletion

‎.github/workflows/update-libs.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
["random-xkcd"]="random-xkcd.cgp"
6868
["snippets"]="snippets.cgp"
6969
["icons-repository"]="icons-repository.cgp"
70+
["rainbow-on-the-go"]="rainbow-on-the-go.cgp"
7071
)
7172
for module in "${!MAP[@]}"; do
7273
src=$(ls "${module}/build/plugin/"*.cgp 2>/dev/null | head -n1)

‎CLAUDE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ If device verification isn't possible in-session, say so explicitly rather than
7878
1. Copy `random-xkcd/` — it's the canonical starting template (small but complete, includes the in-IDE help HTML pattern that submissions are expected to follow).
7979
2. Update `settings.gradle.kts` `rootProject.name`, `build.gradle.kts` `pluginBuilder { pluginName }` + `android { namespace, applicationId }`, and `src/main/AndroidManifest.xml` (`plugin.id`, `plugin.name`, `plugin.main_class`).
8080
3. Add a row to the README's Examples table.
81-
4. If your plugin should ship via the website, add it to the `MAP` array in `.github/workflows/build-plugins.yml` and `.github/workflows/update-libs.yml` so the filename mapping picks it up.
81+
4. If your plugin should ship via the website, add it to the `MAP` array in `.github/workflows/update-libs.yml` so the filename mapping picks it up. (`.github/workflows/build-plugins.yml` needs no change — it auto-discovers plugins by scanning `*/build.gradle.kts` for the plugin-builder Gradle plugin.)
8282

8383
## Plugin review skill
8484

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ See the official [plugin documentation](https://www.appdevforall.org/codeonthego
1818
| [`icons-repository/`](icons-repository/) | Browse a bundled Material icon catalog and import any icon as a Vector Drawable into the active project. |
1919
| [`client-time-tracker/`](client-time-tracker/) | Tracks billable coding sessions per project and generates PDF/Excel/CSV invoices. |
2020
| [`python-tools/`](python-tools/) | Adds Python + Flask project templates, with on-device Python install and run/install/test actions. |
21+
| [`rainbow-on-the-go/`](rainbow-on-the-go/) | Colors matching parentheses, brackets, and braces by nesting depth, with light/dark palettes. |
2122

2223
## Building a plugin
2324

‎rainbow-on-the-go/.gitignore‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Gradle
2+
.gradle/
3+
build/
4+
gradle-app.setting
5+
!gradle-wrapper.jar
6+
.gradletasknamecache
7+
8+
# IDE
9+
.idea/
10+
*.iml
11+
*.ipr
12+
*.iws
13+
.project
14+
.classpath
15+
.settings/
16+
.kotlin/
17+
18+
# Local configuration
19+
local.properties
20+
21+
# OS
22+
.DS_Store
23+
Thumbs.db
24+
25+
# Logs
26+
*.log
27+
28+
# Test outputs
29+
test-results/

‎rainbow-on-the-go/README.md‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# rainbow-on-the-go
2+
3+
A Code On The Go plugin that colors matching parentheses, brackets, and braces by
4+
nesting depth — an opening delimiter and its match share a color, cycling through six
5+
colors (red, orange, yellow, green, blue, purple). Separate palettes are tuned for the
6+
editor's light and dark themes.
7+
8+
It implements the generic `EditorDecorationProvider` API: the plugin computes the colored
9+
spans — bracket detection, nesting depth, theme palettes, and skipping strings/comments —
10+
and the editor merges them on top of the normal syntax highlighting. The IDE has no
11+
knowledge of brackets; it just merges plugin-provided spans. The plugin adds no UI, requests
12+
no permissions, makes no network calls, and reads no files.
13+
14+
> **Note:** this plugin requires a build of Code On The Go that includes the
15+
> `EditorDecorationProvider` API and the editor-side decoration merge. All of the rainbow
16+
> logic lives in this plugin.
17+
18+
## Build
19+
20+
```sh
21+
cd rainbow-on-the-go
22+
./gradlew assemblePlugin # release .cgp -> build/plugin/rainbow-on-the-go.cgp
23+
```
24+
25+
The plugin compiles against `../libs/plugin-api.jar`. If the `EditorDecorationProvider` API
26+
was just added to Code On The Go, refresh the jars first from a local IDE checkout:
27+
28+
```sh
29+
cd ..
30+
./scripts/update-libs.sh --local ../CodeOnTheGo
31+
```
32+
33+
## In-IDE help
34+
35+
A walkthrough is served by the host IDE at
36+
`http://localhost:6174/plugin/org.appdevforall.rainbowonthego/index.html` once installed
37+
(source: `src/main/assets/docs/index.html`). Long-press is wired through
38+
`DocumentationExtension` for the three-tier tooltip help.

‎rainbow-on-the-go/build.gradle.kts‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2+
3+
plugins {
4+
id("com.android.application")
5+
id("org.jetbrains.kotlin.android")
6+
id("com.itsaky.androidide.plugins.build")
7+
}
8+
9+
pluginBuilder {
10+
pluginName = "rainbow-on-the-go"
11+
}
12+
13+
android {
14+
namespace = "org.appdevforall.rainbowonthego"
15+
compileSdk = 34
16+
17+
defaultConfig {
18+
applicationId = "org.appdevforall.rainbowonthego"
19+
minSdk = 26
20+
targetSdk = 34
21+
versionCode = 1
22+
versionName = "1.0.0"
23+
}
24+
25+
buildTypes {
26+
release {
27+
isMinifyEnabled = false
28+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
29+
}
30+
}
31+
32+
compileOptions {
33+
sourceCompatibility = JavaVersion.VERSION_17
34+
targetCompatibility = JavaVersion.VERSION_17
35+
}
36+
37+
testOptions {
38+
unitTests.isReturnDefaultValues = true
39+
}
40+
}
41+
42+
kotlin {
43+
compilerOptions {
44+
jvmTarget.set(JvmTarget.JVM_17)
45+
}
46+
}
47+
48+
dependencies {
49+
// The plugin-api jar is the canonical contract for plugins. Available
50+
// at compile time; the IDE provides it at runtime. This plugin only
51+
// supplies a color palette, so plugin-api + the Kotlin stdlib is all it needs.
52+
compileOnly(files("../libs/plugin-api.jar"))
53+
54+
implementation("org.jetbrains.kotlin:kotlin-stdlib:2.3.0")
55+
56+
testImplementation("junit:junit:4.13.2")
57+
}
58+
59+
tasks.wrapper {
60+
gradleVersion = "8.14.3"
61+
distributionType = Wrapper.DistributionType.BIN
62+
}
63+
64+
// Disable AAR metadata checks that fail under the plugin-builder
65+
// pipeline (Beepy + Forms use the same workaround).
66+
tasks.matching {
67+
it.name.contains("checkDebugAarMetadata") ||
68+
it.name.contains("checkReleaseAarMetadata")
69+
}.configureEach {
70+
enabled = false
71+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
android.useAndroidX=true
2+
android.nonTransitiveRClass=true
3+
kotlin.code.style=official
44.4 KB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)