Skip to content

fix: completion garbage and 500ms TAB delay#30

Merged
alexzhangs merged 3 commits into
developfrom
fix/completion-ansi-and-cache
Jun 10, 2026
Merged

fix: completion garbage and 500ms TAB delay#30
alexzhangs merged 3 commits into
developfrom
fix/completion-ansi-and-cache

Conversation

@alexzhangs

Copy link
Copy Markdown
Owner

Summary

Two bugs in 0.6.1's bash tab completion, reported on macOS bash 3.2:

1. ANSI garbage in completion list

Hitting <TAB> after xsh showed entries like:

x/dotfile/diff^[[0m    x/dotfile/edit^[[0m

Root cause: __xsh_help (xsh.sh:705) unconditionally piped through awk that wraps each line in \033[1m...\033[0m, regardless of whether stdout is a TTY. Any pipe consumer — including the completer's awk '{print $2}' — got the garbage. The opening \033[1m was eaten by awk $2, but the trailing \033[0m stayed attached to the last field.

Fix: Gate the formatter on [ -t 1 ]; pass through cat otherwise. Standard Unix-tools convention — don't emit escapes to non-TTY.

2. ~500ms TAB delay

The completer ran xsh list '*' on every TAB press, walking every loaded library directory.

Fix: Cache the LPUE list in a shell-global var _XSH_COMPLETE_LPUE_CACHE, populated lazily on first need. Helper called directly (not via $(...)) so the assignment lands in the caller's shell. Cold 581ms → warm 1ms (500x speedup).

Defensive belt-and-suspenders

The completer still has a sed ANSI-strip even though the xsh.sh fix makes it unnecessary. Kept because:

  • Robust during mixed-version installs / upgrades
  • Negligible cost (one sed pass on a small string)
  • Lets the completer survive future regressions

Behavior change (very low impact)

Any tooling that grepped ANSI bold codes from piped xsh help / xsh list output now sees plain text. The old behavior was a misfeature — extremely unlikely to have real consumers.

Cache refresh

Cache persists for the shell session. After xsh load/unload/update, refresh with:

unset _XSH_COMPLETE_LPUE_CACHE

Documented in the completer's comment. Auto-clearing from the dispatcher is a future improvement (would require touching xsh.sh's __xsh_load/__xsh_unload/__xsh_update).

Test plan

  • Cold cache populates correctly (~580ms with ~225 LPUEs)
  • Warm cache returns instantly (1ms)
  • unset _XSH_COMPLETE_LPUE_CACHE invalidates and next call is cold
  • xsh list '*' | head produces clean output (no ANSI)
  • xsh help | head produces clean output (no ANSI)
  • Interactive xsh help at terminal still bolded
  • CI green (matrix runs When call xsh help etc. — verifies the non-TTY path matches existing assertions)

🤖 Generated with Claude Code

Two issues reported on bash 3.2 macOS:

1. ANSI suffix in completions, e.g. "x/dotfile/diff^[[0m"
   Root cause: __xsh_help (xsh.sh:705) unconditionally piped through
   awk that wraps every line in \033[1m...\033[0m, regardless of whether
   stdout is a TTY. Pipe consumers — like the completer's awk $2 — got
   garbage. Fix: gate the formatter on [ -t 1 ]; pass through cat otherwise.
   This is the standard Unix-tools convention (don't emit escapes to
   non-TTY). Tested: piped output is clean, terminal output still bolded.

2. ~500ms delay on every TAB press
   Root cause: completer ran 'xsh list "*"' on every TAB, walking every
   loaded library directory. Fix: cache the LPUE list in a shell-global
   var (_XSH_COMPLETE_LPUE_CACHE), populated lazily on first need. Helper
   is called directly (not via $(...)) so the assignment lands in the
   caller's shell rather than a lost subshell.

Empirical: cold 581ms → warm 1ms (500x). Cache survives until manual
unset; documented refresh after xsh load/unload/update is:
  unset _XSH_COMPLETE_LPUE_CACHE

The defensive ANSI-strip sed in the completer is kept even though it's
a no-op once the xsh.sh fix lands, so the completer stays correct during
mixed-version installs / upgrades.

Behavior change (very low impact): tooling that grepped ANSI bold
sequences from piped 'xsh help' output now sees plain text. The old
behavior was a misfeature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.78%. Comparing base (52563cf) to head (fa86229).

Files with missing lines Patch % Lines
xsh.sh 50.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           develop      #30       +/-   ##
============================================
+ Coverage    63.29%   89.78%   +26.49%     
============================================
  Files            3        1        -2     
  Lines          790      666      -124     
============================================
+ Hits           500      598       +98     
+ Misses         290       68      -222     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

alexzhangs and others added 2 commits June 11, 2026 00:55
Add error/guard-branch tests to spec/xsh_func_spec.sh: null-argument paths,
git-clone/git-force-update option and failure handling, lib-manager and
lib-get-cfg-property errors, __xsh_help_self cache rebuild, scripts-type util
import/exec/unimport, the init runtime decorator, load cleanup-on-link-failure,
and environment guards. Library line coverage rises from ~76% to ~90%.

Scope kcov --include-path to xsh.sh in .shellspec. install.sh and boot run as
child bash processes that kcov's bash tracer cannot instrument, so they always
reported 0% despite spec/install_spec.sh exercising them end-to-end; counting
them understated real coverage. They remain integration-tested, not line-counted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alexzhangs alexzhangs merged commit 32c4429 into develop Jun 10, 2026
8 checks passed
@alexzhangs alexzhangs deleted the fix/completion-ansi-and-cache branch June 10, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant