diff --git a/src/f.sh b/src/f.sh index dd67ee5..c600702 100644 --- a/src/f.sh +++ b/src/f.sh @@ -25,7 +25,18 @@ f() { printf '\n[LEARN] "%s" failed. Enter a fix (blank to give up): ' "$*" >&2 read -r n [ -n "$n" ] || return 1 - echo "$*=$n" >> p + # printf, not echo: POSIX leaves it implementation-defined whether + # echo interprets backslash escapes in its argument, and dash/ + # busybox ash both do by default (bash's echo doesn't, unless + # -e). A taught fix containing a literal "\n" -- e.g. any fix + # that itself uses printf '%s\n' internally, which is common and + # idiomatic -- got silently corrupted into a real embedded + # newline on write, breaking p's one-fix-per-line format the + # moment that fix was replayed. Confirmed live: identical fix + # text taught under bash was fine; the same text taught under + # `sh` (dash) truncated mid-line on replay. printf's %s never + # interprets escapes in the substituted value, under any shell. + printf '%s=%s\n' "$*" "$n" >> p FIX="$n" done }