CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/tamboui

Teaches coding agents how to build TUIs with TamboUI correctly: API-level selection, render-thread discipline, display-width safety, CSS-aware element authoring, and JFR conventions.

76

Quality

95%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

list-tamboui-modules.shscripts/

#!/usr/bin/env bash
# list-tamboui-modules.sh — emit TamboUI Gradle modules as JSON.
#
# TamboUI's settings.gradle.kts declares modules in two ways:
#   1. A static `val modules = listOf("tamboui-core", ...)` block.
#   2. Dynamic discovery of demo subdirectories via `includeDemosFrom()`,
#      which scans `demos/` and each `<module>/demos/`.
#
# This script reproduces both: it extracts the static list from settings.gradle.kts
# and walks the filesystem for demo directories the same way Gradle would.
#
# Usage:    list-tamboui-modules.sh [<repo-root>]
# Default:  $PWD
# Output:   stdout — JSON array of objects:
#             [{"name": "tamboui-core", "path": "tamboui-core", "kind": "library"},
#              {"name": "sparkline-demo", "path": "demos/sparkline-demo", "kind": "demo"}, ...]
# Errors:   non-zero exit + diagnostic on stderr if settings.gradle.kts is missing.
#
# Deterministic: same repo state -> same output, sorted by path.

set -euo pipefail

repo_root="${1:-$PWD}"
settings_file="${repo_root%/}/settings.gradle.kts"

if [[ ! -f "$settings_file" ]]; then
  echo "list-tamboui-modules: settings.gradle.kts not found at $settings_file" >&2
  echo "list-tamboui-modules: pass the TamboUI repo root as the first argument, or run from it" >&2
  exit 1
fi

# --- 1. Static modules from `val modules = listOf("...", "...")` ----------------
# Capture the body of the listOf(...) call (single- or multi-line), then pull
# every double-quoted name.  Stops at the closing paren so we do not pick up
# unrelated string literals later in the file.
static_modules=$(
  awk '
    /val[[:space:]]+modules[[:space:]]*=[[:space:]]*listOf[[:space:]]*\(/ { capture = 1 }
    capture {
      print
      if (/\)/) { capture = 0 }
    }
  ' "$settings_file" \
    | { grep -oE '"[^"]+"' || true; } \
    | tr -d '"'
)

# --- 2. Dynamic demos: demos/* directories -------------------------------------
# `includeDemosFrom(File(settingsDir, "demos"), "demos:")` registers every
# subdirectory of demos/ as a project under :demos:<dir>.
demo_paths=()
if [[ -d "${repo_root%/}/demos" ]]; then
  while IFS= read -r -d '' dir; do
    demo_paths+=("demos/$(basename "$dir")")
  done < <(find "${repo_root%/}/demos" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
fi

# --- 3. Dynamic demos: each <module>/demos/* -----------------------------------
# `modules.forEach { module -> includeDemosFrom(File(settingsDir, "$module/demos"), "$module:demos:") }`
while IFS= read -r module; do
  [[ -z "$module" ]] && continue
  module_demos="${repo_root%/}/$module/demos"
  if [[ -d "$module_demos" ]]; then
    while IFS= read -r -d '' dir; do
      demo_paths+=("$module/demos/$(basename "$dir")")
    done < <(find "$module_demos" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
  fi
done <<< "$static_modules"

# --- 4. Emit JSON --------------------------------------------------------------
emit() {
  # $1 = path, $2 = kind
  local path="$1" kind="$2"
  local name="${path##*/}"
  printf '  {"name": "%s", "path": "%s", "kind": "%s"}' "$name" "$path" "$kind"
}

# Build a sorted, deduped, classified list: <path>\t<kind>.
# `|| true` on each AND-list keeps `set -e` from killing the subshell when the
# guard fails on an empty input.
combined=$(
  {
    while IFS= read -r m; do
      [[ -n "$m" ]] && printf '%s\tlibrary\n' "$m" || true
    done <<< "$static_modules"
    for d in "${demo_paths[@]:-}"; do
      [[ -n "$d" ]] && printf '%s\tdemo\n' "$d" || true
    done
  } | sort -u
)

if [[ -z "$combined" ]]; then
  echo "[]"
  exit 0
fi

printf '[\n'
first=1
while IFS=$'\t' read -r path kind; do
  [[ -z "$path" ]] && continue
  if [[ $first -eq 1 ]]; then
    first=0
  else
    printf ',\n'
  fi
  emit "$path" "$kind"
done <<< "$combined"
printf '\n]\n'

CHANGELOG.md

README.md

tile.json