Browse Source
- new commandcomplete.test (6 tests, green 9.0.3 + 8.7): punk::lib::system::incomplete pure-function characterization - the info-complete quoting quirk (a quoted word with unbalanced braces e.g set x "{*}{" is complete standalone but needs extra closers inside a proc body; the pending-opener stack { " { " shrinks per typed closer), single openers, tabs in open braces, escapes, and an incomplete<->info-complete parity property over a case battery
- goals/G-044 detail: the user-specified preserve-list any repl refactor must honour (info-complete parity + quirk, closing-prompt hints incl the accepted single-candidate limitation pinned-not-fixed, raw-mode colour staging in-progress vs submitted, literal tab acceptance with raw-mode marker edit smarts, dim space dots display-only never leaking into submitted strings/history, up/down navigation of MULTILINE editbuf history with recalled entries editable) + testability findings: class_editbuf is console-coupled at its core (add_chunk renders via overtype::renderline against live terminal metrics - cursor-position size probing, DECRQPSR tabstops) so items 3-6 are not unit-characterizable until a console seam exists - G-001 (pluggable console backends / ::opunk::Console test double) is the enabling refactor, not just a feature goal
- goals/G-020 detail: repl interactive-behaviour verification recorded as a driving use case (near-term windows harness: keystroke injection + capture) pending the durable pseudoconsole expect-alternative
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
4 changed files with 175 additions and 1 deletions
@ -0,0 +1,124 @@
|
||||
package require tcltest |
||||
|
||||
package require punk::lib |
||||
|
||||
#Characterization of punk::lib::system::incomplete - the repl's command-completeness / |
||||
#continuation engine (added 2026-07-11 at the user's direction, ahead of any repl |
||||
#refactor goals). Given a partial command string it returns the stack of pending |
||||
#"openers" awaiting closure ({} when the command is complete per [info complete]). |
||||
#The repl uses this for: |
||||
# - deciding whether to evaluate or wait for continuation lines (info complete parity, |
||||
# including Tcl's quoting-rules quirk: a quoted word containing unbalanced braces is |
||||
# complete STANDALONE but inside a braced context (e.g a proc body) brace counting |
||||
# applies, so extra closing characters must be typed - surprising but correct Tcl) |
||||
# - the closing-prompt hints in line and raw mode (the stack top is what the >{ / >" |
||||
# continuation hints render). Known, accepted limitation: when more than one closer |
||||
# candidate exists the repl expresses only one - pinned here as current behaviour, |
||||
# not a fix target. |
||||
# |
||||
#These are PURE function tests runnable under plain tclsh. The raw-mode editbuf side |
||||
#(tab ⇥ markers, dim space dots, colour staging, history navigation) is currently |
||||
#console-coupled (class_editbuf add_chunk renders via overtype::renderline against live |
||||
#terminal metrics) and needs a console seam (G-001) or pseudoconsole harness before it |
||||
#can be characterized - see goals/G-044 detail notes. |
||||
# |
||||
#NOTE: the deliberately-unbalanced case strings cannot appear as braced literals in |
||||
#this (or any) tcl file - they are built from escaped fragments. |
||||
|
||||
namespace eval ::testspace { |
||||
namespace import ::tcltest::* |
||||
variable common { |
||||
set result "" |
||||
} |
||||
|
||||
variable Q "\"" |
||||
variable OB "\{" |
||||
variable CB "\}" |
||||
|
||||
#the user-reported scenario: works standalone, needs extra closers inside a proc body |
||||
variable standalone "set x ${Q}${OB}*${CB}${OB}${Q}" |
||||
variable inproc "proc j ${OB}${CB} ${OB}\n set x ${Q}${OB}*${CB}${OB}${Q}" |
||||
|
||||
test commandcomplete_standalone_quoted_braces {a quoted word containing unbalanced braces is a complete command standalone}\ |
||||
-setup $common -body { |
||||
variable standalone |
||||
lappend result [info complete $standalone] |
||||
lappend result [punk::lib::system::incomplete $standalone] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list 1 {}] |
||||
|
||||
test commandcomplete_inproc_progression {the same line inside a proc body needs extra closers - the pending-opener stack shrinks as each is typed}\ |
||||
-setup $common -body { |
||||
variable inproc |
||||
variable Q |
||||
variable CB |
||||
set s $inproc |
||||
lappend result [info complete $s] [punk::lib::system::incomplete $s] |
||||
append s "\n${CB}" |
||||
lappend result [info complete $s] [punk::lib::system::incomplete $s] |
||||
append s "\n${Q}" |
||||
lappend result [info complete $s] [punk::lib::system::incomplete $s] |
||||
append s "\n${CB}" |
||||
lappend result [info complete $s] [punk::lib::system::incomplete $s] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list 0 [list \{ \" \{ \"] 0 [list \{ \"] 0 [list \{] 1 {}] |
||||
|
||||
test commandcomplete_single_openers {unterminated quote, brace and bracket each report their single pending opener}\ |
||||
-setup $common -body { |
||||
variable Q |
||||
variable OB |
||||
lappend result [punk::lib::system::incomplete "puts ${Q}hello"] |
||||
lappend result [punk::lib::system::incomplete "puts ${OB}hello"] |
||||
lappend result [punk::lib::system::incomplete "puts \[clock seconds"] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list [list \"] [list \{] [list \[]] |
||||
|
||||
test commandcomplete_tab_in_open_brace {literal tabs inside an open braced context do not disturb the pending-opener stack}\ |
||||
-setup $common -body { |
||||
variable OB |
||||
lappend result [punk::lib::system::incomplete "set z ${OB}\n line1\ttabbed"] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list [list \{]] |
||||
|
||||
test commandcomplete_escapes {backslash-escaped braces and quotes do not open/close contexts}\ |
||||
-setup $common -body { |
||||
variable Q |
||||
lappend result [info complete "puts \\${Q}"] [punk::lib::system::incomplete "puts \\${Q}"] |
||||
lappend result [info complete "puts \\\{"] [punk::lib::system::incomplete "puts \\\{"] |
||||
#an escaped quote inside an open quoted word leaves the quote pending |
||||
lappend result [punk::lib::system::incomplete "puts ${Q}a\\${Q}b"] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list 1 {} 1 {} [list \"]] |
||||
|
||||
test commandcomplete_parity_with_info_complete {incomplete returns the empty list exactly when info complete reports true (property over the case battery)}\ |
||||
-setup $common -body { |
||||
variable Q |
||||
variable OB |
||||
variable CB |
||||
variable standalone |
||||
variable inproc |
||||
set battery [list {puts hello} $standalone $inproc "$inproc\n${CB}" "$inproc\n${CB}\n${Q}" "$inproc\n${CB}\n${Q}\n${CB}" "puts ${Q}hello" "puts ${OB}hello" "puts \[clock seconds" "set z ${OB}\n line1\ttabbed" "puts \\${Q}" "if ${OB}1${CB} ${OB}\n puts ok\n${CB}"] |
||||
set mismatches [list] |
||||
foreach c $battery { |
||||
set emptystack [expr {[llength [punk::lib::system::incomplete $c]] == 0}] |
||||
if {$emptystack != [info complete $c]} { |
||||
lappend mismatches $c |
||||
} |
||||
} |
||||
lappend result $mismatches |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list {}] |
||||
} |
||||
tcltest::cleanupTests ;#needed to produce test summary line. |
||||
Loading…
Reference in new issue