From e25537bb50a77812cf379bf60a620356329ac0d9 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Wed, 5 Aug 2026 18:45:09 +1000 Subject: [PATCH] punk::ansi 0.1.4: ansistring RANGE argdoc states the pinned contract Documentation-only bump. The RANGE punk::args -help (and the doctools comment) now document the behaviours pinned by the 2026-08-05 ansistring coverage survey (ansi/ansistring.test), replacing the underspecified "including the ANSI codes in effect" wording: - SGR codes re-applied at each plain-text run in merged (canonicalized) form - style-equivalent but NOT byte-identical to the original. - SGR-only carriage: other sequence types (cursor movement, OSC, charset shifts) are not re-emitted. - Codes after the last requested grapheme are not included; trailing SGR state is retrievable with ansistring INDEXCODE end+1. - Index semantics: end-relative expressions, one-sided clamping, empty-string returns for both-beyond-same-end and inverted ranges (tcl string range consistency). The @cmd -summary reworded from "ANSI codes preserved" (overclaimed) to "SGR styling re-applied". Open design questions stay deliberately undocumented as contract - trailing codes on literal end (the shared TODO with opunk::Str RANGE and its whole-span $this shortcut divergence), non-SGR retention, charset/gx0 handling - recorded in code comments and G-151 Notes. ansi subtree 71/71 green (tclsh90); usage render verified carrying the new content. Minted modules/punk/ansi-0.1.4.tm via make.tcl modules; bootsupport/vfscommon promotion left to the next promotion cycle. Claude-Session: https://claude.ai/code/session_0156PuejSCGjgeGb7jiABrDU Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- src/modules/punk/ansi-999999.0a1.0.tm | 20 +++++++++++++++----- src/modules/punk/ansi-buildversion.txt | 3 ++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/modules/punk/ansi-999999.0a1.0.tm b/src/modules/punk/ansi-999999.0a1.0.tm index fade8ad1..e7794650 100644 --- a/src/modules/punk/ansi-999999.0a1.0.tm +++ b/src/modules/punk/ansi-999999.0a1.0.tm @@ -11581,12 +11581,22 @@ tcl::namespace::eval punk::ansi::ansistring { @id -id ::punk::ansi::ansistring::RANGE @cmd -name punk::ansi::ansistring::RANGE\ -summary\ - "Substring between grapheme positions, with ANSI codes preserved."\ + "Substring between grapheme positions, with SGR styling re-applied."\ -help\ "Return the substring of string between grapheme positions startindex - and endindex inclusive (positions as for ansistring INDEX), including - the ANSI codes in effect for those graphemes. - end-relative index expressions are supported." + and endindex inclusive (positions as for ansistring INDEX), with the + ANSI SGR codes in effect for those graphemes re-applied at each + plain-text run - so the range renders as the original did. + The result is style-equivalent but not byte-identical: code stacks + are re-emitted in merged (canonicalized) form, only SGR codes are + carried (other sequence types - cursor movement, OSC, charset + shifts - are not re-emitted), and codes after the last requested + grapheme are not included (the SGR state after the whole string is + retrievable with ansistring INDEXCODE end+1). + end-relative index expressions are supported. An index beyond the + string clamps to the nearest end; if both indices fall beyond the + same end, or startindex resolves past endindex, an empty string is + returned (as for tcl string range)." @values -min 3 -max 3 string -type string startindex -type indexexpression @@ -11596,7 +11606,7 @@ tcl::namespace::eval punk::ansi::ansistring { proc RANGE {string startindex endindex} { #*** !doctools #[call [fun RANGE] [arg string] [arg startindex] [arg endindex]] - #[para]Returns the substring of string between the character positions startindex and endindex, inclusive, where the character positions are determined by INDEX. The returned substring will include any ANSI codes that are in effect for those characters. + #[para]Returns the substring of string between the character positions startindex and endindex, inclusive, where the character positions are determined by INDEX. The ANSI SGR codes in effect for those characters are re-applied at each plain-text run in merged (canonicalized) form - style-equivalent but not byte-identical to the original; non-SGR codes and codes after the last requested character are not re-emitted (see INDEXCODE end+1 for trailing SGR state). #TODO - special case processing for end+n and equivalents to return trailing ANSI codes as well. #(similar to INDEXCODE) diff --git a/src/modules/punk/ansi-buildversion.txt b/src/modules/punk/ansi-buildversion.txt index a7c5ee63..cbdbf203 100644 --- a/src/modules/punk/ansi-buildversion.txt +++ b/src/modules/punk/ansi-buildversion.txt @@ -1,5 +1,6 @@ -0.1.3 +0.1.4 #First line must be a semantic version number #all other lines are ignored. +#0.1.4 - documentation-only: ansistring RANGE argdoc + doctools comment now state the pinned contract (tests ansi/ansistring.test, 2026-08-05 coverage survey): merged/canonicalized SGR re-emission (style-equivalent, not byte-identical), SGR-only carriage (non-SGR sequence types not re-emitted), trailing-code exclusion with INDEXCODE end+1 as the retrieval mechanism, and clamping/empty-range semantics. Summary reworded (was 'codes preserved' - overclaimed). Open design questions (trailing codes on literal end, non-SGR retention, charset/gx0 handling) stay as code TODO/review comments and G-151 Notes - deliberately not promised in the doc. #0.1.3 - documentation-only: grepstr -return summarydict choicelabel corrected - the summary dict's 'linemap' key is always present (the old text claimed it appeared only with -n; actual always-present behaviour pinned in tests ansi/grepstr.test). Reconciliation deferred from the grepstr characterization wave to the punk::ns hygiene pass. #0.1.2 - documentation-only: PUNKARGS argdoc blocks added for punk::ansi::codetype (is_sgr_reset, has_sgr_leadingreset, is_cursor_move_in_line, has_all_effective, get_effective_types, is_gx/is_gx_open/is_gx_close, sgr_merge), punk::ansi::sequence_type (is_Fe7/is_Fe/is_Fe8, is_Fp, is_Fs, is_nF, is_3Fp, is_code7/is_code8/is_code, classify), punk::ansi::ta (detect_in_list, detectcode, detectcode_in_list, detect_g0, detect_open, detect_st_open, detect_csi, detect_sgr, split_at_codes, split_codes, split_codes_single, get_codes_single) and punk::ansi::ansistring (VIEW, COUNT, length, trimleft/trimright/trim, INDEX, INDEXCHAR, RANGE, INSERT, INDEXABSOLUTE, INDEXCOLUMNS, COLUMNINDEX); ::punk::ansi::sequence_type added to punk::args::register NAMESPACES so its argdocs are discoverable