Storage comment: say each fact once, and say what hunk names may contain rather than calling them hostile.
commit c24db4dd240d6fdd76f9233a335342aeddddfd3a · parent 8618f82f0e
· browse this tree
Ximianth, 2026-10-23 14:48:11 UTC
The commit-at-the-end rule lives at the commit point in parse, and the reason assoc kinds are declared moves there too, beside the declare it explains. The pid line says what the pid is for, since nothing refuses on it yet.
diff --git a/lib/testmark/document.bash b/lib/testmark/document.bash index 52547d4..6f6e80f 100644 --- a/lib/testmark/document.bash +++ b/lib/testmark/document.bash @@ -2,17 +2,15 @@ ## Sourced by testmark.bash; the functions here assume they run inside `_testmark_call`. # shellcheck disable=SC2034,SC2178 # shellcheck does not follow namerefs: writes through them look unused, and reusing a name as one looks like an array turned string -# Storage: a document's state lives only in globals named after its handle, `_testmark_KIND_HANDLE`: +# Storage: a document's state lives only in globals named after its handle, `_testmark_KIND_HANDLE`, one per kind in _testmark_kinds: # lines indexed: the lines, each keeping its "\n" (a file's last line may lack one), CRLF made LF # start, end assoc by hunk name: the body's line range [start, end) in lines # info assoc by hunk name: the info string # names the hunk names in document order, each ending in "\n" -# pid $BASHPID at parse; state changes refuse other pids -# So forgetting a handle is one `unset` of whole variables, and nothing else needs cleaning up. -# Names are built only from handles checked against [A-Za-z0-9_]+, and kinds have no "_", so two handles' names never meet. -# Parse works in locals and commits at its very end, so a failed parse leaves nothing behind. -# Globals are reached through namerefs; assoc ones are declared first, since a nameref to an undeclared name makes an indexed array. -# Hunk names come from documents, so they are hostile as keys: on some bash versions, arithmetic, `[[ -v ]]`, `unset`, and `printf -v` on an element run `$(...)` from inside its key. +# pid $BASHPID at parse, for refusing state changes from a subshell +# So forgetting a handle is one `unset` per kind, and nothing else needs cleaning up. +# Variable names are built only from handles that pass _testmark_handle, and kinds have no "_", so two handles' variables never meet. +# Hunk names come from documents and may contain shell syntax: on some bash versions, arithmetic, `[[ -v ]]`, `unset`, and `printf -v` on an element run `$(...)` from inside its key. # So touch name-keyed elements only as `a[$k]=v`, `"${a[$k]}"`, `"${a[$k]-}"`, `${a[$k]+set}`, and `"${!a[@]}"`. _testmark_kinds=(lines start end info names pid) @@ -108,6 +106,7 @@ _testmark_parse() { } # Parsed without error; only now are globals written. + # Assoc kinds are declared first, since a nameref to an undeclared name makes an indexed array. declare -gA "_testmark_start_$h" "_testmark_end_$h" "_testmark_info_$h" local -n g_lines=_testmark_lines_$h g_start=_testmark_start_$h g_end=_testmark_end_$h g_info=_testmark_info_$h local -n g_names=_testmark_names_$h g_pid=_testmark_pid_$h