A run of Unicode code points now needs one pair of carets, not one pair
each: ^9053 53EF 9053^ renders the characters adjacently, and a single
character inside such a run stands for itself. An invalid code point is
an error naming the position that wrote it, rather than an apology
rendered into the finished document; noncharacters are refused alongside
surrogates; and a code point that lands on a Klammertext special is safe
through the re-reads that assemble a document. The character tables now
produce the precomposed form, so a diacritic written as ^a" and one typed
directly are the same text to a search or a copy-paste.
"kdesc -u" describes how to write a Unicode character, with tables of
glyphs beside the codes that produce them. It is new and not yet
complete: it predates the sequence form and the typeface klammer below.
A typeface and a style are no longer both called "font". A typeface is a
family resolved by name; a style code is the one letter naming a type
style. So @document takes :serif_typeface and its siblings, a table takes
:style, captions take :caption_style and :caption_size, the uniform scale
is :text_scale, and the command is "kdesc --typeface". This renames
arguments a document may already use; an old name is a located error
rather than a silent omission.
@typeface sets a passage in another typeface for the length of that
passage:
@typeface Noto Sans Egyptian Hieroglyphs | ^132AA 133CF^ :scale 1.5 @
Writing the klammer is the whole declaration -- the document resolves the
typeface, embeds it in what it produces, and carries its license along.
Two typefaces for scripts no text font covers now ship with Klammertext:
Noto Sans Egyptian Hieroglyphs and Noto Sans Cuneiform. Every typeface in
the distribution now carries its license file.
(from dev 61e598698891)
218 lines
11 KiB
Bash
Executable File
218 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# kdesc_test.sh — the kdesc command's interface.
|
|
#
|
|
# The flag structure was reorganised 2026-08-11
|
|
# (notes/modifying_the_kdesc_arguments.md) on two rules:
|
|
#
|
|
# * a flag a user reaches for often gets a single letter (-k klammers,
|
|
# -t targets, -c character codes, -i input); a more specialised topic gets
|
|
# a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets,
|
|
# --coverage, --klammersets, --font);
|
|
# * -v says how much to show about the command's PROCESSING and never what
|
|
# its RESULT contains. So the katom regex column is "--katoms full" and
|
|
# the coverage file column is "--coverage all", not verbosity levels.
|
|
#
|
|
# "-k" is the one rename that changes a name's MEANING rather than retiring
|
|
# it: it used to show katom types (now --katoms). A name-based guard cannot
|
|
# catch that -- the old spelling still works and does something else -- so
|
|
# these tests pin the new meaning down.
|
|
#
|
|
# Usage: ./kdesc_test.sh (needs KLAMMERTEXT_HOME set; kdesc on PATH)
|
|
# Exit code: 0 if all tests pass, 1 otherwise.
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
KDESC=kdesc
|
|
K=${KLAMMERTEXT_HOME:?KLAMMERTEXT_HOME must be set}
|
|
DIR="$(cd "$(dirname "$0")" && pwd)/coverage"
|
|
|
|
red=$'\033[31m'
|
|
green=$'\033[32m'
|
|
bold=$'\033[1m'
|
|
reset=$'\033[0m'
|
|
|
|
plain() { sed 's/\x1b\[[0-9;]*m//g'; }
|
|
|
|
# GNU coreutils' "timeout" is NOT present on macOS, and Homebrew's is named
|
|
# "gtimeout", so a bare "timeout" made this suite fail WHOLESALE there -- every
|
|
# case, because the command never ran at all (found on Olion, 2026-08-16). The
|
|
# guard is a safety net against a hung command, not part of what is being
|
|
# tested, so it is optional: bound the command where the tool exists, run it
|
|
# directly where it does not.
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
limited() { timeout 60 "$@"; }
|
|
elif command -v gtimeout >/dev/null 2>&1; then
|
|
limited() { gtimeout 60 "$@"; }
|
|
else
|
|
limited() { "$@"; }
|
|
fi
|
|
|
|
# shows NAME PATTERN CMD... — exits 0 and the output matches PATTERN.
|
|
shows() {
|
|
local name="$1" pattern="$2"; shift 2
|
|
local out status
|
|
out=$(limited "$@" 2>&1 | plain); status=$?
|
|
if [ $status -gt 128 ]; then
|
|
echo "${red}FAIL${reset} $name — died by signal $((status-128))"; FAIL=$((FAIL+1)); return
|
|
fi
|
|
if printf '%s' "$out" | grep -Eq -- "$pattern"; then
|
|
echo "${green}PASS${reset} $name"; PASS=$((PASS+1))
|
|
else
|
|
echo "${red}FAIL${reset} $name — no line matching [$pattern]"
|
|
echo " got: $(printf '%s' "$out" | head -2)"; FAIL=$((FAIL+1))
|
|
fi
|
|
}
|
|
|
|
# absent NAME PATTERN CMD... — the output does NOT match PATTERN.
|
|
absent() {
|
|
local name="$1" pattern="$2"; shift 2
|
|
if limited "$@" 2>&1 | plain | grep -Eq -- "$pattern"; then
|
|
echo "${red}FAIL${reset} $name — unexpected match [$pattern]"; FAIL=$((FAIL+1))
|
|
else
|
|
echo "${green}PASS${reset} $name"; PASS=$((PASS+1))
|
|
fi
|
|
}
|
|
|
|
echo "${bold}kdesc interface tests${reset}"
|
|
echo "====================="
|
|
echo
|
|
|
|
echo "-- the single-letter flags --"
|
|
shows " 1. -k lists klammers" '@table' "$KDESC" -k
|
|
shows " 2. -t lists targets" 'html' "$KDESC" -t
|
|
shows " 3. -c lists character codes" '.' "$KDESC" -c
|
|
shows " 4. -i reads the named input" '@x' "$KDESC" -i "$DIR/split.k" -k
|
|
# -u describes how to write a Unicode character. Asserted by OUTCOME, on
|
|
# the two things the section must carry however its prose is rewritten:
|
|
# the ^...^ notation it teaches, and a rendered character beside its code
|
|
# point -- the whole point of the section is that a reader sees the glyph
|
|
# they are about to write. It does NOT pin the prose, which is meant to
|
|
# grow (as of 2026-08-25 the section predates the sequence form and the
|
|
# typeface klammer, and does not yet mention either).
|
|
shows " 4a. -u describes the Unicode syntax" '\^0418\^' "$KDESC" -u
|
|
# The rendered glyph, as UTF-8 BYTE escapes: macOS ships bash 3.2, which
|
|
# expands $'\xHH' but not $'\U...' (that difference failed this suite's
|
|
# sibling on Olion, 2026-08-23).
|
|
shows " 4b. ... and shows the characters" $'\xf0\x93\x8a\xaa' "$KDESC" -u
|
|
|
|
echo
|
|
echo "-- the multi-letter topics --"
|
|
shows " 5. --katoms lists katom types" 'katom' "$KDESC" --katoms
|
|
shows " 6. --argtypes lists argtypes" 'fraction' "$KDESC" --argtypes
|
|
shows " 7. --rewrite lists rewrites" '.' "$KDESC" --rewrite
|
|
shows " 8. --optionsets lists sets" 'caption_args' "$KDESC" --optionsets
|
|
|
|
echo
|
|
echo "-- result detail is a word, not a verbosity level --"
|
|
shows " 9. --katoms full adds the regex column" 'Regex' "$KDESC" --katoms full
|
|
absent "10. --katoms alone omits it" 'Regex' "$KDESC" --katoms
|
|
shows "11. --coverage all adds the file column" 'sks/table/table\.k' "$KDESC" --coverage all
|
|
absent "12. --coverage alone omits it" 'sks/table/table\.k' "$KDESC" --coverage
|
|
# "all" is one word for both kinds of missing information: if you want some of
|
|
# it you probably want all of it. It shows an empty REPORTING category -- a
|
|
# designer's checklist of the shapes a klammer set can have -- but not an
|
|
# empty PROBLEM one, which would state the opposite of the "Needs attention"
|
|
# banner above it.
|
|
# Against a FIXTURE, not the SKS: which categories are empty there changes as
|
|
# the klammer set is worked on, and a test pinned to that state fails for a
|
|
# reason that has nothing to do with what it is testing. (It did: adopting
|
|
# ".*" in the SKS made "All targets, declared" non-empty.)
|
|
shows "12a. --coverage all shows an empty reporting category" \
|
|
'All targets, declared \(0\)' "$KDESC" --klammersets none -i "$DIR/cycle.k" --coverage all
|
|
absent "12b. ... hidden without it" \
|
|
'All targets, declared \(0\)' "$KDESC" --klammersets none -i "$DIR/cycle.k" --coverage
|
|
absent "12c. an empty problem category stays hidden" \
|
|
'Declared but never defined \(0\)' "$KDESC" --klammersets none -i "$DIR/cycle.k" --coverage all
|
|
absent "13. -v adds no result detail" 'Regex' "$KDESC" --katoms -v 3
|
|
|
|
echo
|
|
echo "-- -v is about processing only --"
|
|
shows "14. -v names the input it read" 'input_filenames' "$KDESC" -i "$DIR/clean.k" -t -v 1
|
|
absent "15. ... and is silent without it" 'input_filenames' "$KDESC" -i "$DIR/clean.k" -t
|
|
|
|
echo
|
|
echo "-- the klammer search --"
|
|
shows "16. a name matches" '@table' "$KDESC" -k table
|
|
absent "17. ... and others are excluded" '@document' "$KDESC" -k table
|
|
shows "18. matching is case-insensitive" '@table' "$KDESC" -k TABLE
|
|
shows "19. a description word matches" '@' "$KDESC" -k verbatim
|
|
# The words after -k are one phrase, and whitespace is collapsed on both
|
|
# sides -- a description written across several lines in a .k file must still
|
|
# match a phrase typed on one.
|
|
shows "20. several words are one phrase" '@' "$KDESC" -k displayed verbatim
|
|
shows "21. ... with runs of space collapsed" '@' "$KDESC" -k displayed verbatim
|
|
shows "22. no match says so" 'No klammer names or descriptions contained "zzqq"\.' "$KDESC" -k zzqq
|
|
absent "23. ... and lists nothing" '^ @' "$KDESC" -k zzqq
|
|
|
|
echo
|
|
echo "-- the subcommand words --"
|
|
shows "24. --coverage help explains" 'Coverage commands' "$KDESC" --coverage help
|
|
shows "25. --katoms help explains" 'Katom commands' "$KDESC" --katoms help
|
|
shows "26. an unknown coverage word" 'Unrecognized coverage command' "$KDESC" --coverage nonsense
|
|
shows "27. an unknown katom word" 'Unrecognized katom command' "$KDESC" --katoms nonsense
|
|
|
|
echo
|
|
echo "-- provenance: -i shows what the INPUT defines --"
|
|
# A klammerset is loaded so the input can be ANALYSED against it, but it is
|
|
# not what the user asked about. A designer wants the klammers this file
|
|
# defines; a reader of an unfamiliar document wants the custom ones it
|
|
# carries. So "-i" restricts every listing to definitions from outside the
|
|
# loaded klammersets -- while the klammersets stay loaded.
|
|
PROV=$(mktemp /tmp/kdesc_prov.XXXXXX.k)
|
|
printf '@@shout.k s : Say it loudly @@\n@@shout.html :: <b>*s*</b> @@\n' > "$PROV"
|
|
shows "32. -i lists the input's own klammer" '@shout' "$KDESC" -i "$PROV" -k
|
|
absent "33. ... and not the klammerset's" '@table' "$KDESC" -i "$PROV" -k
|
|
shows "34. without -i the klammerset is shown" '@table' "$KDESC" -k
|
|
# The klammerset is still LOADED: a coverage derived from a klammer it
|
|
# supplies proves the analysis saw it even though the report does not.
|
|
DERIVE=$(mktemp /tmp/kdesc_derive.XXXXXX.k)
|
|
printf '@@wave.k s : Wave @@\n@@wave :: @i *s* @ @@\n' > "$DERIVE"
|
|
shows "35. coverage is derived through the unlisted klammerset" \
|
|
'@wave +html pdf tex txt +from @i' "$KDESC" -i "$DERIVE" --coverage
|
|
absent "36. ... and the klammerset is not reported" '@table' "$KDESC" -i "$DERIVE" --coverage
|
|
# A klammer the input REDEFINES came from the klammerset, but the input
|
|
# changed it -- which is exactly what a reader needs to know.
|
|
REDEF=$(mktemp /tmp/kdesc_redef.XXXXXX.k)
|
|
printf '@@i.html ::: <em class="mine">*text*</em> @@\n' > "$REDEF"
|
|
shows "37. a redefined klammer is the input's too" '@i' "$KDESC" -i "$REDEF" -k
|
|
# An input that declares its own klammerset is still the input.
|
|
DECL=$(mktemp -d /tmp/kdesc_decl.XXXXXX)
|
|
mkdir -p "$DECL/own"
|
|
printf '@@@klammerset own | A designer set @@@\n@@yell.k s : Yell @@\n@@yell.html :: <b>*s*</b> @@\n' \
|
|
> "$DECL/own/own.k"
|
|
shows "38. an input declaring a klammerset is not filtered out" \
|
|
'@yell' "$KDESC" -i "$DECL/own/own.k" -k
|
|
rm -rf "$PROV" "$DERIVE" "$REDEF" "$DECL"
|
|
|
|
echo
|
|
echo "-- the usage text --"
|
|
shows "28. -k shows its optional argument" '\-k \[<text>\]' "$KDESC"
|
|
shows "29. -i shows its filename" '\-i <filename>' "$KDESC"
|
|
# Ordered by likely use: the single letters come before the long names.
|
|
# Line numbers, not a multi-line pattern -- grep is line-oriented.
|
|
usage=$(limited "$KDESC" 2>&1 | plain)
|
|
k_line=$(printf '%s\n' "$usage" | grep -n -- '-k \[<text>\]' | head -1 | cut -d: -f1)
|
|
katoms_line=$(printf '%s\n' "$usage" | grep -n -- '--katoms' | head -1 | cut -d: -f1)
|
|
if [ -n "$k_line" ] && [ -n "$katoms_line" ] && [ "$k_line" -lt "$katoms_line" ]; then
|
|
echo "${green}PASS${reset} 30. -k is listed before --katoms"; PASS=$((PASS+1))
|
|
else
|
|
echo "${red}FAIL${reset} 30. usage order: -k at line $k_line, --katoms at $katoms_line"
|
|
FAIL=$((FAIL+1))
|
|
fi
|
|
|
|
echo
|
|
echo "-- a no-result search is not an error --"
|
|
limited "$KDESC" -k zzqq >/dev/null 2>&1
|
|
if [ $? -eq 0 ]; then
|
|
echo "${green}PASS${reset} 31. finding nothing exits 0"; PASS=$((PASS+1))
|
|
else
|
|
echo "${red}FAIL${reset} 31. finding nothing exits nonzero"; FAIL=$((FAIL+1))
|
|
fi
|
|
|
|
echo
|
|
echo "====================="
|
|
echo "Results: ${PASS} passed, ${FAIL} failed"
|
|
[ "$FAIL" -eq 0 ] || exit 1
|
|
exit 0
|