Literal @c, @source_listing with :marker, and a large-directory speedup

Three changes.

@c now takes its content literally, like @code -- it is the inline form
and @code the block form of the same thing.  The named close "c@" is
required, and characters that are special in a target no longer break
the file: @c a_b c@ renders correctly everywhere.  The Markdown
converter stops quoting inline code, since nothing needs protecting.

@source_file is renamed @source_listing.  Code read from a file is its
own klammer; @code is only for a block written inline (its never-
implemented :filename and :pattern options are removed).  The new
:marker P option lists the region between two lines that are exactly
//P, so the source file declares its own extractable regions.  A marker
missing or not appearing exactly twice is an error, never a fallback.

Rendering a document that sits in a large directory was paying a
recursive walk of that directory's whole tree on every @eval -- 27
seconds for a document that renders in a third of one.  The walk is now
a non-recursive look decided once per directory.

Assembled from dev commit 071b1b183de4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 16:58:50 +02:00
parent 8b38a34841
commit bd39d9a369
8 changed files with 284 additions and 47 deletions

View File

@@ -124,6 +124,63 @@ check_eq "17. @eval result ^@ survives read-back as @" '@'
# Klammertext -- a resolved @ in the result must not be re-parsed.
check_eq "18. :after_apply phase: raw result, @ intact" 'A @ B' --klammersets none -t u -s '@@@target u | up :after_apply string.capwords @@@ a ^@ b'
# --- Literal klammers and REMOVED text (TODO #40, fixed 2026-08-16) ---
#
# mark_literal_klammer_content() runs FIRST in process_katoms(), before
# mark_ignored_katoms() takes out the "#" forms. That ordering is deliberate --
# a literal klammer's content must be marked before anything can interpret what
# is inside it, or removal would take a "#" belonging to the literal body -- but
# it meant the scan saw text the writer had removed, so a literal klammer merely
# NAMED in a comment was read as an opening delimiter, went unclosed, and failed
# the whole file. Andy's minimal case was `ktext -s "# @code" -d`.
#
# Both directions need a case, and the second is the one a careless fix breaks.
# A literal klammer with a literal parameter, defined inline: the engine tier
# loads no klammer set, so @code is not available here.
LIT='@@lit.k t.literal : A literal klammer @@ @@lit.t :: [*t*] @@'
echo
echo "-- literal klammers named inside removed text --"
check_eq "19. named in a # comment: removed, not an opening delimiter" \
'kept' --klammersets none -t t -s "$T $LIT # @lit
kept"
check_eq "20. ... including the realistic case that raised it" \
'kept' --klammersets none -t t -s "$T $LIT # @image and @lit share the same arguments.
kept"
check_eq "21. named inside #[ ... ]#" \
'kept' --klammersets none -t t -s "$T $LIT #[ @lit ]# kept"
check_eq "22. ... and inside NESTED #[ #[ ]# ]#" \
'kept' --klammersets none -t t -s "$T $LIT #[ a #[ @lit ]# b ]# kept"
check_eq "23. after ## the rest of the file is gone" \
'kept' --klammersets none -t t -s "$T $LIT kept ## @lit"
echo
echo "-- and the converse: a # INSIDE literal content is CONTENT --"
# The direction a careless fix breaks. Skipping removed text must happen only
# while looking for an OPENING delimiter; once one is found the scan jumps past
# the whole span, so a "#" in the content is never examined.
# A BARE "#" -- not a quoted "^#". The quoted form would pass whether or not
# the content was treated as literal, and so would prove nothing.
#
# The use must be in a FILE with the definition in "-s", not both in one "-s":
# mark_literal_klammer_content() only knows the klammers REGISTERED WHEN IT
# RUNS, and "-s" is processed as one unit, so a literal klammer defined and used
# in the same string is not yet literal while that string is scanned. "-s" is
# processed before the input files, so this ordering is what a real document
# has -- the klammer set is loaded first.
LITUSE=$(mktemp /tmp/escape_lit.XXXXXX).kt
printf '@lit a # b lit@\n' > "$LITUSE"
# "-d" is required here and nowhere else in this suite: with a FILE input ktext
# writes a file instead of displaying, so stdout would be empty.
check_eq "24. a bare # inside literal content survives as content" \
'[a # b]' "$LITUSE" --klammersets none -t t -d -s "$T $LIT"
rm -f "$LITUSE"
check_eq "25. a real literal klammer still works after a comment naming it" \
'[x]' --klammersets none -t t -s "$T $LIT # mentions @lit here
@lit x lit@"
rm -f "$ERR"
echo