From b8e38025c54810c364523c6ec5161436b0f34f85 Mon Sep 17 00:00:00 2001 From: Brett Kinny Date: Sat, 10 Oct 2026 17:31:34 +1000 Subject: [PATCH] Add TTT as an optional terminal editor --- README.md | 5 +++-- scripts/e2e-test.sh | 3 ++- scripts/lib/tools.yaml | 10 ++++++++++ scripts/squarebox-setup.sh | 2 +- scripts/squarebox-update.sh | 1 + setup.sh | 22 +++++++++++++++++----- tests/test-provision-install-failures.sh | 4 ++-- tests/test-provision-state.sh | 10 ++++++++++ 8 files changed, 46 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 174069a..b018d76 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ scripted installs). Values use the same keys as `sqrbx-setup`: |----------|---------| | `SQUAREBOX_AI` | AI assistants (`claude,copilot,gemini,codex,opencode,pi,omp`) | | `SQUAREBOX_SDKS` | language SDKs (`node,python,go,dotnet,rust`) | -| `SQUAREBOX_EDITORS` | editors (`micro,edit,fresh,helix,nvim`; Helix launches as `hx`) | +| `SQUAREBOX_EDITORS` | editors (`micro,edit,fresh,helix,nvim,ttt`; Helix launches as `hx`) | | `SQUAREBOX_TUIS` | TUI tools (`lazygit,gh-dash,yazi,elio`) | | `SQUAREBOX_MULTIPLEXERS` | multiplexers (`tmux,zellij,herdr`) | | `SQUAREBOX_GIT_NAME` / `SQUAREBOX_GIT_EMAIL` | git identity (when no host gitconfig) | @@ -294,6 +294,7 @@ installed editor instead. |------|----------|-------------| | [micro](https://github.com/micro-editor/micro) | Go | Modern, intuitive terminal editor | | [edit](https://github.com/microsoft/edit) | Rust | Terminal text editor (Microsoft) | +| [ttt](https://github.com/eugenioenko/ttt) | Go | Terminal Text Tool | | [fresh](https://github.com/sinelaw/fresh) | Rust | Modern terminal text editor | | [helix](https://github.com/helix-editor/helix) | Rust | Modal editor (Kakoune-inspired) | | [nvim](https://github.com/neovim/neovim) | C/Lua | Neovim | @@ -612,7 +613,7 @@ container environment variables (set to an empty string to opt out of a tier): |----------|---------|---------| | `SQUAREBOX_DC_AI` | `claude` | AI assistants (`claude,copilot,gemini,codex,opencode,pi,omp`) | | `SQUAREBOX_DC_SDKS` | `node` | SDKs (`node,python,go,dotnet,rust`) | -| `SQUAREBOX_DC_EDITORS` | _(none)_ | Editors (`micro,edit,fresh,helix,nvim`; Helix launches as `hx`) | +| `SQUAREBOX_DC_EDITORS` | _(none)_ | Editors (`micro,edit,fresh,helix,nvim,ttt`; Helix launches as `hx`) | | `SQUAREBOX_DC_TUIS` | _(none)_ | TUI tools (`lazygit,gh-dash,yazi,elio`) | | `SQUAREBOX_DC_MULTIPLEXERS` | _(none)_ | Multiplexers (`tmux,zellij,herdr`) | diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh index 52b12e7..b964bd3 100755 --- a/scripts/e2e-test.sh +++ b/scripts/e2e-test.sh @@ -225,7 +225,7 @@ suite_setup_editors() { # Pre-seed selections in /workspace/.squarebox/ mkdir -p /workspace/.squarebox echo "opencode,pi" > /workspace/.squarebox/ai-tool - echo "micro,edit,fresh,helix,nvim" > /workspace/.squarebox/editors + echo "micro,edit,fresh,helix,nvim,ttt" > /workspace/.squarebox/editors echo "lazygit,gh-dash,yazi,elio" > /workspace/.squarebox/tuis echo "tmux,zellij,herdr" > /workspace/.squarebox/multiplexer echo "node,go" > /workspace/.squarebox/sdks @@ -262,6 +262,7 @@ suite_setup_editors() { run_test "3.7a2 pi installed" command -v pi run_test "3.7b micro installed" command -v micro run_test "3.7c edit installed" command -v edit + run_test "3.7g ttt installed" command -v ttt run_test "3.7d fresh installed" command -v fresh run_test "3.7e helix installed as hx" command -v hx run_test "3.7f nvim installed" command -v nvim diff --git a/scripts/lib/tools.yaml b/scripts/lib/tools.yaml index d323ddb..fde73a0 100644 --- a/scripts/lib/tools.yaml +++ b/scripts/lib/tools.yaml @@ -206,6 +206,16 @@ tools: group: setup verification: github-release-digest + ttt: + repo: eugenioenko/ttt + version_prefix: v + artifact: ttt-linux-{goarch} + method: binary + binaries: ttt + dest: user + group: setup + verification: github-release-digest + helix: repo: helix-editor/helix version_prefix: "" diff --git a/scripts/squarebox-setup.sh b/scripts/squarebox-setup.sh index 664f8dc..0f92b27 100644 --- a/scripts/squarebox-setup.sh +++ b/scripts/squarebox-setup.sh @@ -32,7 +32,7 @@ usage() { git Git identity (name, email) github GitHub CLI authentication ai AI coding assistants (claude, copilot, gemini, codex, opencode, pi, omp) - editors Text editors (micro, edit, fresh, helix/hx, nvim) + editors Text editors (micro, edit, fresh, helix/hx, nvim, ttt) tuis TUI tools (lazygit, gh-dash, yazi, elio) multiplexers Terminal multiplexers (tmux, zellij, herdr) sdks SDKs (node, python, go, dotnet, rust) diff --git a/scripts/squarebox-update.sh b/scripts/squarebox-update.sh index 059eb4f..a61df80 100755 --- a/scripts/squarebox-update.sh +++ b/scripts/squarebox-update.sh @@ -299,6 +299,7 @@ starship_current() { starship --version 2>/dev/null | _extract_first_version; } ghdash_current() { gh-dash --version 2>/dev/null | _extract_first_version; } glow_current() { glow --version 2>/dev/null | _extract_first_version; } micro_current() { micro --version 2>/dev/null | _extract_first_version; } +ttt_current() { ttt --version 2>/dev/null | _extract_first_version; } fresh_current() { fresh --version 2>/dev/null | _extract_first_version; } edit_current() { edit --version 2>/dev/null | _extract_first_version; } helix_current() { hx --version 2>/dev/null | _extract_first_version; } diff --git a/setup.sh b/setup.sh index d760083..af5f198 100755 --- a/setup.sh +++ b/setup.sh @@ -841,7 +841,7 @@ fi if [ -f "$EDITOR_DEFAULT_CONFIG" ]; then editor_default_prev=$(cat "$EDITOR_DEFAULT_CONFIG") case "$editor_default_prev" in - nano|micro|edit|fresh|hx|nvim) ;; + nano|micro|edit|fresh|hx|nvim|ttt) ;; *) echo "Warning: ignoring invalid saved default editor '$editor_default_prev'." >&2; editor_default_prev="" ;; esac fi @@ -858,6 +858,7 @@ if $INTERACTIVE; then edit) gum_selected="${gum_selected:+$gum_selected,}edit" ;; fresh) gum_selected="${gum_selected:+$gum_selected,}fresh" ;; helix) gum_selected="${gum_selected:+$gum_selected,}helix" ;; + ttt) gum_selected="${gum_selected:+$gum_selected,}ttt" ;; nvim) gum_selected="${gum_selected:+$gum_selected,}nvim" ;; esac done @@ -865,7 +866,7 @@ if $INTERACTIVE; then gum_args=(--no-limit --header "Select text editors to install:") [ -n "$gum_selected" ] && gum_args+=(--selected "$gum_selected") if ! selected=$(gum choose "${gum_args[@]}" \ - "micro" "edit" "fresh" "helix" "nvim"); then + "micro" "edit" "fresh" "helix" "nvim" "ttt"); then cancel_setup fi editor_list="" @@ -876,13 +877,14 @@ if $INTERACTIVE; then else echo "Select text editors to install (comma-separated, or 'all', or press Enter to skip):" echo " Nano is always available and remains the fallback default unless you choose an installed editor instead." - for ed_item in "1:micro:micro" "2:edit:edit" "3:fresh:fresh" "4:helix:helix (hx)" "5:nvim:nvim"; do + for ed_item in "1:micro:micro" "2:edit:edit" "3:fresh:fresh" "4:helix:helix (hx)" "5:nvim:nvim" "6:ttt:ttt"; do num="${ed_item%%:*}"; rest="${ed_item#*:}"; key="${rest%%:*}"; label="${rest#*:}" case "$key" in micro) desc="modern, intuitive terminal editor" ;; edit) desc="terminal text editor (Microsoft)" ;; fresh) desc="modern terminal text editor" ;; helix) desc="modal editor (Kakoune-inspired)" ;; + ttt) desc="Terminal Text Tool" ;; nvim) desc="Neovim" ;; esac if [[ ",$editor_prev," == *",${key},"* ]]; then @@ -891,13 +893,13 @@ if $INTERACTIVE; then echo " ${num}) ${label} — ${desc}" fi done - read -rp "Selection [1,2,3,4,5/all/skip]: " editor_selection + read -rp "Selection [1,2,3,4,5,6/all/skip]: " editor_selection if [ -z "$editor_selection" ] && [ -n "$editor_prev" ]; then editor_list="$editor_prev" else editor_list="" if [ "$editor_selection" = "all" ]; then - editor_list="micro,edit,fresh,helix,nvim" + editor_list="micro,edit,fresh,helix,nvim,ttt" elif [ -n "$editor_selection" ]; then for item in $(echo "$editor_selection" | tr ',' ' '); do case "$item" in @@ -905,6 +907,7 @@ if $INTERACTIVE; then 2) editor_list="${editor_list:+$editor_list,}edit" ;; 3) editor_list="${editor_list:+$editor_list,}fresh" ;; 4) editor_list="${editor_list:+$editor_list,}helix" ;; + 6) editor_list="${editor_list:+$editor_list,}ttt" ;; 5) editor_list="${editor_list:+$editor_list,}nvim" ;; esac done @@ -975,6 +978,12 @@ install_fresh() { command -v fresh >/dev/null 2>&1 } +install_ttt() { + if command -v ttt &>/dev/null; then echo "TTT already installed, skipping."; return 0; fi + run_with_spinner "Installing TTT..." sb_install ttt latest || return 1 + command -v ttt >/dev/null 2>&1 +} + install_helix() { if command -v hx &>/dev/null && [ -d "$HOME/.config/helix/runtime" ]; then echo "Helix already installed, skipping." @@ -1082,6 +1091,9 @@ for editor in $(echo "$editor_list" | tr ',' ' '); do fresh) if install_fresh; then installed_editors+=("fresh"); committed_editors+=("fresh") else record_failure "Fresh installation failed; new Selection was not committed"; [[ ",$editor_prev," == *",fresh,"* ]] && committed_editors+=("fresh"); fi ;; + ttt) + if install_ttt; then installed_editors+=("ttt"); committed_editors+=("ttt") + else record_failure "TTT installation failed; new Selection was not committed"; [[ ",$editor_prev," == *",ttt,"* ]] && committed_editors+=("ttt"); fi ;; helix) if install_helix; then installed_editors+=("hx"); committed_editors+=("helix") else record_failure "Helix installation failed; new Selection was not committed"; [[ ",$editor_prev," == *",helix,"* ]] && committed_editors+=("helix"); fi ;; diff --git a/tests/test-provision-install-failures.sh b/tests/test-provision-install-failures.sh index f6b4550..9288ccf 100755 --- a/tests/test-provision-install-failures.sh +++ b/tests/test-provision-install-failures.sh @@ -212,10 +212,10 @@ assert_true "grep -qx 'herdr latest' '$HERDR_CASE/sb-install.calls'" \ # Audit every adjacent setup-tier sb_install caller, not just the two callers # that originally had a successful config write after the failed install. EDITORS_CASE="$TMP/editors" -run_selected_section editors $'micro\nedit\nfresh\nhelix\nnvim' "$EDITORS_CASE" +run_selected_section editors $'micro\nedit\nfresh\nhelix\nnvim\nttt' "$EDITORS_CASE" assert_true "[ \"\$(cat '$EDITORS_CASE/setup.rc')\" -ne 0 ] && [ -z \"\$(cat '$EDITORS_CASE/state/editors')\" ]" \ "all editor sb_install failures propagate without committing Selections" -for editor in micro edit fresh helix nvim; do +for editor in micro edit fresh helix nvim ttt; do assert_true "grep -qx '$editor latest' '$EDITORS_CASE/sb-install.calls'" \ "$editor failure audit exercises its sb_install caller" done diff --git a/tests/test-provision-state.sh b/tests/test-provision-state.sh index e9886f3..16a16da 100755 --- a/tests/test-provision-state.sh +++ b/tests/test-provision-state.sh @@ -191,6 +191,16 @@ assert_true "grep -qx 'set -g mouse on' '$HOME_DIR/.config/tmux/tmux.conf'" "rec assert_true "[ \"\$(cat '$STATE/multiplexer')\" = tmux ]" "successful reconciliation preserves the saved Selection" assert_true "[ \"\$(cat '$STATE/editor-default')\" = fresh ] && grep -qx \"export EDITOR='fresh'\" '$HOME_DIR/.squarebox-editor-aliases'" "reconcile preserves a non-first default editor Selection" +# TTT is a valid saved default and remains selected during reconciliation. +printf '#!/usr/bin/env bash\nexit 0\n' > "$BIN/ttt" +chmod +x "$BIN/ttt" +printf 'micro,ttt\n' > "$STATE/editors" +printf 'ttt\n' > "$STATE/editor-default" +HOME="$HOME_DIR" SQUAREBOX_STATE_DIR="$STATE" \ + SQUAREBOX_TOOL_LIB="$FIXTURE_LIB" SQUAREBOX_TOOLS_YAML=/dev/null \ + PATH="$BIN:$PATH" bash "$ROOT/setup.sh" --reconcile-box >"$TMP/ttt-reconcile.out" 2>"$TMP/ttt-reconcile.err" +assert_true "grep -qx 'micro,ttt' '$STATE/editors' && grep -qx ttt '$STATE/editor-default' && grep -qx \"export EDITOR='ttt'\" '$HOME_DIR/.squarebox-editor-aliases'" "reconcile preserves TTT Selection and default editor" + for ai_binary in copilot gemini codex pi omp; do printf '#!/usr/bin/env bash\nexit 0\n' > "$BIN/$ai_binary" done