Assembled from klammertext-dev f344a37d772c. The commands, the library,
the Standard Klammer Set, the reflection klammerset and the Python
binding build and run natively on Windows (MSYS2 UCRT64 gcc, python.org
Python), and both test tiers pass there. doc/install/windows_source_install.md
is the fifth install guide: a source install parallel to the Linux and
macOS ones, verified by following it on a pristine Windows 11.
Behaviour on every system: paths Klammertext prints use forward slashes;
output is LF; the command line is UTF-8 on Windows; @eval :shell is a
POSIX shell command everywhere -- on Windows it runs the sh Klammertext
ships, BusyBox for Windows (win/busybox/, GPLv2, with its licence and the
source pointer). KLAMMERTEXT_FONTS and KLAMMERTEXT_KLAMMERSETS are lists in
the system's PATH convention (';' on Windows). On Linux and macOS nothing
observable changes.
158 lines
5.2 KiB
Bash
Executable File
158 lines
5.2 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# filename_test.sh — Regression tests for filenames containing spaces.
|
|
#
|
|
# Filenames may contain spaces. The rules (see CLAUDE.md "Output directory
|
|
# policy" and the filename-list functions in mac/file.cpp):
|
|
# - argv boundaries are authoritative: a shell-quoted "my file.kt" is one
|
|
# filename (Argv stores the original argv vector; nothing re-splits it).
|
|
# - A filename LIST is separated by a standalone "/" token (whitespace on
|
|
# both sides) — never a legal input filename, since "/" alone is the
|
|
# root directory.
|
|
# - Rescue: without a separator, whitespace-split names that do not exist
|
|
# are greedily rejoined with their neighbors into names that do; the
|
|
# regrouping is announced on stderr.
|
|
# - A leading "~/" expands to $HOME (shells do not expand a quoted tilde).
|
|
#
|
|
# Engine tier: uses --klammersets none; no SKS.
|
|
#
|
|
# Usage: ./filename_test.sh
|
|
# Exit code: 0 if all tests pass, 1 otherwise.
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
KTEXT=ktext
|
|
K=${KLAMMERTEXT_HOME:?KLAMMERTEXT_HOME must be set}
|
|
|
|
red=$'\033[31m'
|
|
green=$'\033[32m'
|
|
bold=$'\033[1m'
|
|
reset=$'\033[0m'
|
|
|
|
# Scratch input files
|
|
DIR=$(mktemp -d)
|
|
trap 'rm -rf "$DIR"' EXIT
|
|
mkdir "$DIR/my dir"
|
|
printf 'ALPHA\n' > "$DIR/my file.kt"
|
|
printf 'BETA\n' > "$DIR/b.kt"
|
|
printf 'GAMMA\n' > "$DIR/my dir/c.kt"
|
|
cd "$DIR" || exit 1
|
|
|
|
# check TEST_NAME EXPECTED_STDOUT EXPECTED_STDERR_SUBSTRING KTEXT_ARGS...
|
|
# EXPECTED_STDERR_SUBSTRING may be "" (no stderr requirement).
|
|
check() {
|
|
local test_name="$1" expected="$2" err_needle="$3"
|
|
shift 3
|
|
local output status errfile=$DIR/.stderr
|
|
output=$("$KTEXT" "$@" 2>"$errfile")
|
|
status=$?
|
|
output=$(printf '%s' "$output" | sed -e 's/[ \t]*$//' | grep -v '^$')
|
|
if [ $status -ne 0 ]; then
|
|
echo "${red}FAIL${reset} $test_name — ktext exited $status"
|
|
echo " stderr: $(head -3 "$errfile")"
|
|
FAIL=$((FAIL + 1))
|
|
return
|
|
fi
|
|
if [ "$output" != "$expected" ]; then
|
|
echo "${red}FAIL${reset} $test_name"
|
|
echo " expected: [$expected]"
|
|
echo " got: [$output]"
|
|
FAIL=$((FAIL + 1))
|
|
return
|
|
fi
|
|
if [ -n "$err_needle" ] && ! grep -qF "$err_needle" "$errfile"; then
|
|
echo "${red}FAIL${reset} $test_name — expected stderr to contain [$err_needle]"
|
|
echo " stderr: $(head -3 "$errfile")"
|
|
FAIL=$((FAIL + 1))
|
|
return
|
|
fi
|
|
echo "${green}PASS${reset} $test_name"
|
|
PASS=$((PASS + 1))
|
|
}
|
|
|
|
# check_error TEST_NAME EXPECTED_SUBSTRING KTEXT_ARGS...
|
|
# Expects a nonzero exit whose combined output contains EXPECTED_SUBSTRING.
|
|
check_error() {
|
|
local test_name="$1" needle="$2"
|
|
shift 2
|
|
local output status
|
|
output=$("$KTEXT" "$@" 2>&1)
|
|
status=$?
|
|
if [ $status -eq 0 ]; then
|
|
echo "${red}FAIL${reset} $test_name — expected an error, got exit 0"
|
|
FAIL=$((FAIL + 1))
|
|
return
|
|
fi
|
|
if echo "$output" | grep -qF "$needle"; then
|
|
echo "${green}PASS${reset} $test_name"
|
|
PASS=$((PASS + 1))
|
|
else
|
|
echo "${red}FAIL${reset} $test_name — expected output to contain [$needle]"
|
|
echo " output: $(echo "$output" | head -3)"
|
|
FAIL=$((FAIL + 1))
|
|
fi
|
|
}
|
|
|
|
echo "${bold}Filename-with-spaces tests${reset}"
|
|
echo "======================="
|
|
|
|
check "1. quoted filename with a space is one file" \
|
|
"ALPHA" "" \
|
|
"my file.kt" -d --klammersets none
|
|
|
|
# The regrouping is a DERIVED value -- the command completed a name the input
|
|
# left ambiguous -- so since 2026-08-15 it is reported at "-v 1" and the
|
|
# default run is silent. Silence is safe because a rescue only succeeds when
|
|
# the joined name names an existing file: a mistyped name fails instead of
|
|
# resolving to something else.
|
|
check "2. unquoted spaces are rescued into an existing file" \
|
|
"ALPHA" "" \
|
|
my file.kt -d --klammersets none
|
|
|
|
check "2a. ... silently at the default verbosity" \
|
|
"ALPHA" "" \
|
|
my file.kt -d --klammersets none
|
|
|
|
check "2b. ... and reported at -v 1" \
|
|
"ALPHA" "interpreting \"my file.kt\" as one filename" \
|
|
my file.kt -d --klammersets none -v 1
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|MSYS*)
|
|
# The MSYS shell rewrites a bare "/" argument into the MSYS root
|
|
# (C:/msys64/) before a native program sees it; a Windows user in
|
|
# PowerShell or cmd is not affected, so the feature is not what fails.
|
|
echo "SKIP 3. standalone / separates a filename list (the MSYS shell rewrites a bare /)";;
|
|
*)
|
|
check "3. standalone / separates a filename list" \
|
|
"ALPHA
|
|
BETA" "" \
|
|
my file.kt / b.kt -d --klammersets none
|
|
;;
|
|
esac
|
|
|
|
check "4. space in a directory component" \
|
|
"GAMMA" "" \
|
|
"my dir/c.kt" -d --klammersets none
|
|
|
|
check "5. quoted name that exists is never split (b.kt also exists)" \
|
|
"ALPHA" "" \
|
|
"my file.kt" -d --klammersets none
|
|
|
|
HOME="$DIR" check "6. quoted ~/ expands to \$HOME inside ktext" \
|
|
"BETA" "" \
|
|
"~/b.kt" -d --klammersets none
|
|
|
|
check "7. @read argument keeps its internal space" \
|
|
"ALPHA" "" \
|
|
-s '@read my file.kt @' -d --klammersets none
|
|
|
|
check_error "8. unrescuable name is reported as written" \
|
|
"no such.kt" \
|
|
"no such.kt" -d --klammersets none
|
|
|
|
echo
|
|
echo "======================="
|
|
echo "Results: ${green}$PASS passed${reset}, ${red}$FAIL failed${reset}"
|
|
[ $FAIL -eq 0 ]
|