Browse Source

more ansi and repl fixes

master
Julian Noble 9 months ago
parent
commit
be20491421
  1. 3
      src/modules/punk/ansi-999999.0a1.0.tm
  2. 2
      src/modules/punk/repl-0.1.tm
  3. 94
      src/testansi/fox_goat.ans
  4. 409
      src/vendormodules/overtype-1.5.9.tm
  5. 2401
      src/vendormodules/overtype-1.6.0.tm

3
src/modules/punk/ansi-999999.0a1.0.tm

@ -100,7 +100,8 @@ namespace eval punk::ansi::class {
#overflow is a different concept - perhaps not particularly congruent with the idea of the textblock as a mini terminal emulator. #overflow is a different concept - perhaps not particularly congruent with the idea of the textblock as a mini terminal emulator.
#overflow effectively auto-expands the block(terminal?) width #overflow effectively auto-expands the block(terminal?) width
#overflow and wrap both being true won't make sense unless we implement a max_overflow concept #overflow and wrap both being true won't make sense unless we implement a max_overflow concept
set o_rendered [overtype::left -overflow 0 -wrap 1 -appendlines 1 $b $o_raw] #set o_rendered [overtype::left -overflow 0 -wrap 1 -appendlines 1 $b $o_raw]
set o_rendered [overtype::left -overflow 0 -wrap 1 -width 80 -appendlines 1 "" $o_raw]
#set o_rendered_what $o_raw #set o_rendered_what $o_raw
set o_render_dimensions $dimensions set o_render_dimensions $dimensions
} }

2
src/modules/punk/repl-0.1.tm

@ -1945,7 +1945,7 @@ proc repl::repl_process_data {inputchan type chunk stdinlines prompt_config} {
} }
} }
} }
set last_cursor_colun [$editbuf cursor_column] set last_cursor_column [$editbuf cursor_column]
} else { } else {
#rputs stderr "->0byte read stdin" #rputs stderr "->0byte read stdin"
if {[chan eof $inputchan]} { if {[chan eof $inputchan]} {

94
src/testansi/fox_goat.ans

@ -0,0 +1,94 @@

ワワ ワ ワ ワロワ ワワ゚ロ゚ ワワワワワワロワワワワワワワワ
ワ ワ ワ ワワ
ワ ロワロ゚゚゚ロロワロロ ロロワ゚゚ ゚ ワ゚ロ ロ ロロロロロロロロロロロロロロロワワワワ
゚゚ワワロワ ゚ロロ ワロワ ワ
゚ワワ゚゚ロ゚゚ワ ゚ ワロロロロ゚ロロワ ゚゚ロ゚ ワ ロワロワ ロ
ロロロワワ゚゚゚゚゚ロロロロロロロロロロワワワワワワワワ ワ
ワ
゚゚ワワ ロワロワロ ワワ゚゚゚ ゚ ワワ゚ ゚゚
ワワロ ワ゚ ロ ロロロロ ゚゚ロ゚゚ワワワワワ゚゚゚゚゚ロロロロロ゚゚゚゚゚ロワ
ロ゚゚゚ワワロロ゚ワワ゚゚ワワ ゚ロワ゚ワワ
ワロ゚ロワワ ロ ロロロロ ワワワ゚゚
゚゚゚ワワワワワ゚゚゚゚゚ロロ
ロ ロ゚ワワロロ゚ワワワワワワ゚゚゚ ゚゚ ゚゚ワロワワワ゚゚
ロ゚ロワ ロ ロロロロ ゚ワロ゚ワロロロ゚゚ロ゚゚ワ
ワ
゚ロロロワワ゚゚゚゚ ゚ ロロロロワ ゚゚゚゚ロロロロロロ゚゚ ゚゚ロワ゚
ロ ロロロロ ワロワワワロワワ゚ワ゚ワ
ロ゚ロロワ゚゚゚ ロロ゚ ロ゚ ロ゚ロロロ゚ロロワロ ロロロロ ゚ ロ゚
ワロロロ ロロロワ゚ワ ワ ゚ワ゚
゚ロ゚ ロ゚゚ロ゚ワロ ロロワロ ロロロロ ロ゚ワ ロロロ ワ ロロロ
 ロ ゚゚ロ
ロワワワワワロロワ ロ゚ワロ ゚ ワワワワワ
ロ ロロロロワロロロロ ロロ
ワ ロワロ゚ ゚゚ロ゚ ゚ワワワ ワロロ゚゚ロ゚
゚ ワ゚ロロロロロ゚ ロロ
ロワロロ゚ ゚゚ワワワ゚ロロロロ ロロ゚ ワロ゚゚ ワワワワ
ロロ ゚ロロ゚
ロワ゚ロワ゚゚ ワ ワ゚ワワワワロロロロロロロ ロロ ワワロロロロロ゚ ロロ
゚゚ロワ ゚
ロ゚ ワ ロワロ゚゚゚゚゚ワワ゚ワロロロロロロロロロロロワロワロロロロロロロ
゚゚ワロワロ
ロ ワ ロロ゚ ゚゚ワワロロロロロロロロロロ゚ロロロロロロロロロ゚ロロ
ロロ
ロロ゚ ワ ワワロロロロロ゚ロロロロロロロワ゚ロロロロワワロロロ
ワロ゚ロロ
゚ ロワロワロ゚゚ワワワロロロロロロ ロロロロロロ゚ ゚ロロロロロロ
゚ ゚゚
ロワ゚ロ゚ロ ゚゚ワロロロロロロロロワ゚ロロ゚ワ ロ ゚ロ゚ロ
ロ ワワワワワ ロ
ロ ゚ワワロロロロロロロロロロワロロロロ ロ ワ ゚゚
ワロロロ゚゚゚゚゚ワ
ワワロロロロロロロロロロロロロロロロ ロ ロロワ゚ロワワ゚゚ワ
゚ワロロロロロロロワ
ワワワワワワワ゚ロロロロロロロロロロロロロロロ ロロロ ロロロワ゚ロロ
ワ゚ロロロ゚ ワ゚ ゚ロ ゚ワ
ワロロロロロロロロワワワロロロロロロロロロロロロロロロ゚ワロ゚ロ ロロロワワ
ロ゚ロワ゚ロロロロロロロワワ ワ゚ ゚
ロロロロロロロロロロワワワワロロロロロロロロロロワ゚ロロロロロ ワロロ ロロロ ワロ
゚゚ロロロワ ロロロロロロロロロロロ゚ワ
゚ロロ゚ワロロロロロロ ゚ワロロロロロロロロロロロロロ ロロロロロロ ロロ ロ ロロロ 
゚゚゚゚ロロロロロロロロロロロロロロロ゚ロロ
゚ ゚ワロロロロロ ロロロロロロ゚ロロロロロロロ゚゚ ゚ロロロワ゚ロワ ロ ロロロ 
゚゚゚ロロロロロロロ ロロロロロロロワワワ
ロ゚ロロロロ ロロロロロロロワ゚ロロロロワ゚ ロロワ゚ロロ ゚ ロ゚゚
ワワワ ロ゚ロロ゚ロロ゚ワロロロロロロロロ ワワワワワ゚
ロロロロロロロワワロロロロロロロロロロワロ゚ワ゚ロ゚ロワ ロロロロワ゚ ワワワワワ ゚ワロロ ワ
ロロロロロロロロロ ロ ワワワワ ワ
ワロ ゚ロ゚ロロロロロロロロロロロロロロロロロロロロ ロロ゚ロロワワワ゚゚ワ゚ロロ ワワロロロ
ロロロロロ ゚ワ ロロ
ロワ ロ゚ロロロロロロ ロロロロロロロロロロロロ ロロロロ゚ロロロロ ゚ワ゚ ワロロロロロ
ロロロワロワ゚ワ
ロロ ロワ ゚ ゚ ゚ロロロロロロロロロロ゚ワロロロ ワ ロワ ワ゚゚゚゚ワワワ
ワ ロロロロロロロロロロロロロワ ゚ロワ ゚ ゚
゚ワワロ゚ワ゚ロロロロロロ゚゚ワロロ゚゚ロ ロロロロワワワワ゚ ワ゚゚゚゚゚゚
゚゚゚゚゚゚゚゚゚゚゚゚゚ワロロロワロロ
゚゚ロワ゚゚゚゚ワロロロロロロ ロロ゚゚ワワロ ロ ロロロロロロロロロロロロワワワワワワ
ワワワワワワワワワワワワワ ワワワロ ゚
゚ ロワ ワ ロワロ ロロ゚ロロロロ゚ワロロロロワ ワ゚ロ ロ ロ゚ロロロロロロロロロロロ
ロロロロロロロロロロロロロロロロ ワワロロ ゚
ワワロ゚ロロ゚ロ゚゚ロロロ゚ ゚゚ロロロ ゚ワロ ロ ロ ロ ワ ロワワワ゚゚゚゚゚ロロロ
ロロロロロロロロロロロロロロロロ ワ ゚゚ロ゚゚ワワ
゚ロ ゚゚ ワワワロ゚゚ ゚ロロ ワ゚ワ゚ワ ゚ロロワ゚゚゚゚ロ゚ 
ロロロロ ロロロロワワ ワワワワ ワワワワ ワ ワ ワ ゚ロワロ゚ ワ
ワロロロロロロ゚゚゚゚ ゚ロロロ゚ロロロワロワワワ ゚゚゚゚゚゚ ロロロロ ゚゚゚ 
゚゚ロワロロワロロロ゚ワワ ロ
ロロロロワ ワワワワ ワロロワ ゚゚゚゚゚ ゚゚゚ 
ワ゚゚゚ワ ロロロロ ロロロロ ゚゚゚゚゚゚゚゚ロ゚゚ ワロロ゚゚ ロロ゚ ロロ゚ワ
ロワワ ワワロロロワワ ゚ ゚ロロロ ワ ワ゚゚ロ ロ ゚ロ
ロロ ロロロロ ロロロロロロロ ロ ロロ ワワロワ ゚ ロロロ ロ ロ
゚゚゚゚゚゚゚゚ ゚゚ ゚ ロワワ ワ゚゚ ロ ワ ゚
ロワロロロロワロロロロロロロワロワロロワ ゚゚゚ワワロロ゚゚ロワ ロ゚
George Ramos (C)Copyright 1992
ワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワワ
ワワワワワワワワワワワワワワワ
ロロワ ワロ ロ ロ ワワロロロ ワワロ゚ワ゚ロワ゚ロ゚ワロロロロ ロロ ゚ロ ロ ワ゚ロロロワ ワロ ロ ロ ワワロロロ゚ワワロロ゚ワ゚
ロロ ロロワ ワロロ
ロロロ ロロ ワ ロ ワロロロロ ワロロ ロ ロロ゚ワ゚ロロロロ ゚ ロ ロワ ロ ロ ロロロロ ロロ ワ ロ ワロロロロ ロロ゚ロ ロ 
ロ ゚ ロロ ロロロ
ロロロワロロワロワロワワワロロロワロロロロワロロワロロロワロロロワロワロワロロワロワワロロロロロワロロワロワロワワワロロロロワワロロロワロ
ロワロワロロワロロロ



409
src/vendormodules/overtype-1.5.9.tm

@ -209,6 +209,10 @@ proc overtype::string_columns {text} {
# a cursor start position other than top-left is a possible addition to consider. # a cursor start position other than top-left is a possible addition to consider.
#see editbuf in punk::repl for a more stateful ansi-processor. Both systems use loops over overtype::renderline #see editbuf in punk::repl for a more stateful ansi-processor. Both systems use loops over overtype::renderline
proc overtype::left {args} { proc overtype::left {args} {
#*** !doctools
#[call [fun overtype::left] [arg args] ]
#[para] usage: ?-transparent [0|1]? ?-overflow [1|0]? ?-ellipsis [1|0]? ?-ellipsistext ...? undertext overtext
# @c overtype starting at left (overstrike) # @c overtype starting at left (overstrike)
# @c can/should we use something like this?: 'format "%-*s" $len $overtext # @c can/should we use something like this?: 'format "%-*s" $len $overtext
variable default_ellipsis_horizontal variable default_ellipsis_horizontal
@ -268,6 +272,7 @@ proc overtype::left {args} {
set underblock [string map $norm $underblock] set underblock [string map $norm $underblock]
set overblock [string map $norm $overblock] set overblock [string map $norm $overblock]
#set underlines [split $underblock \n] #set underlines [split $underblock \n]
#underblock is a 'rendered' block - so width height make sense #underblock is a 'rendered' block - so width height make sense
@ -276,7 +281,11 @@ proc overtype::left {args} {
} else { } else {
set colwidth $opt_width set colwidth $opt_width
} }
set underlines [lines_as_list -ansiresets 1 $underblock] if {$underblock eq ""} {
set underlines [list "\x1b\[0m\x1b\[0m"]
} else {
set underlines [lines_as_list -ansiresets 1 $underblock]
}
set overlines [split $overblock \n] set overlines [split $overblock \n]
#overblock height/width isn't useful in the presence of an ansi input overlay with movements. The number of lines may bear little relationship to the output height #overblock height/width isn't useful in the presence of an ansi input overlay with movements. The number of lines may bear little relationship to the output height
@ -296,7 +305,11 @@ proc overtype::left {args} {
set outputlines $underlines set outputlines $underlines
set underlay_resets [list] set underlay_resets [list]
for {set overidx 0} {$overidx < [llength $overlines]} {incr overidx} { set overidx 0
while {$overidx < [llength $overlines]} {
flush stdout
set overtext [lindex $overlines $overidx]; lset overlines $overidx "" set overtext [lindex $overlines $overidx]; lset overlines $overidx ""
set undertext [lindex $outputlines [expr {$row -1}]] set undertext [lindex $outputlines [expr {$row -1}]]
set renderedrow $row set renderedrow $row
@ -311,6 +324,7 @@ proc overtype::left {args} {
} }
#review insert_mode. As an 'overtype' function whose main function is not interactive keystrokes - insert is secondary - #review insert_mode. As an 'overtype' function whose main function is not interactive keystrokes - insert is secondary -
#but even if we didn't want it as an option to the function call - to process ansi adequately we need to support IRM (insertion-replacement mode) ESC [ 4 h|l #but even if we didn't want it as an option to the function call - to process ansi adequately we need to support IRM (insertion-replacement mode) ESC [ 4 h|l
set LASTCALL [list -info 1 -insert_mode $insert_mode -autowrap_mode $autowrap_mode -transparent $opt_transparent -width $colwidth -exposed1 $opt_exposed1 -exposed2 $opt_exposed2 -overflow $opt_overflow -cursor_column $col -cursor_row $row $undertext $overtext]
set rinfo [renderline -info 1 -insert_mode $insert_mode -autowrap_mode $autowrap_mode -transparent $opt_transparent -width $colwidth -exposed1 $opt_exposed1 -exposed2 $opt_exposed2 -overflow $opt_overflow -cursor_column $col -cursor_row $row $undertext $overtext] set rinfo [renderline -info 1 -insert_mode $insert_mode -autowrap_mode $autowrap_mode -transparent $opt_transparent -width $colwidth -exposed1 $opt_exposed1 -exposed2 $opt_exposed2 -overflow $opt_overflow -cursor_column $col -cursor_row $row $undertext $overtext]
set instruction [dict get $rinfo instruction] set instruction [dict get $rinfo instruction]
set insert_mode [dict get $rinfo insert_mode] set insert_mode [dict get $rinfo insert_mode]
@ -330,6 +344,8 @@ proc overtype::left {args} {
dict set replay_codes_underlay [expr {$renderedrow+1}] [dict get $rinfo replay_codes_underlay] dict set replay_codes_underlay [expr {$renderedrow+1}] [dict get $rinfo replay_codes_underlay]
lset replay_codes_overlay [expr $overidx+1] [dict get $rinfo replay_codes_overlay] lset replay_codes_overlay [expr $overidx+1] [dict get $rinfo replay_codes_overlay]
#-- todo - detect looping properly #-- todo - detect looping properly
if {$row > 1 && $overtext ne "" && $unapplied eq $overtext && $post_render_row == $row} { if {$row > 1 && $overtext ne "" && $unapplied eq $overtext && $post_render_row == $row} {
puts stderr "overtype::left loop?" puts stderr "overtype::left loop?"
@ -341,7 +357,6 @@ proc overtype::left {args} {
set cursor_saved_position $c_saved_pos set cursor_saved_position $c_saved_pos
set cursor_saved_attributes $c_saved_attributes set cursor_saved_attributes $c_saved_attributes
} }
set cursor_restore_required [dict get $rinfo cursor_restore_required]
#background line is narrower than data in line #background line is narrower than data in line
@ -383,7 +398,7 @@ proc overtype::left {args} {
if {$opt_appendlines} { if {$opt_appendlines} {
lappend outputlines $rendered lappend outputlines $rendered
} else { } else {
#? #?
lset outputlines [expr {$renderedrow-1}] $rendered lset outputlines [expr {$renderedrow-1}] $rendered
} }
} }
@ -391,42 +406,12 @@ proc overtype::left {args} {
set nextprefix "" set nextprefix ""
if {$cursor_restore_required} {
if {[dict exists $cursor_saved_position row]} {
set row [dict get $cursor_saved_position row]
set col [dict get $cursor_saved_position column]
#puts stdout "restoring: row $row col $col [ansistring VIEW $cursor_saved_attributes] [a] unapplied [ansistring VIEWCODES $unapplied]"
#set nextprefix $cursor_saved_attributes
lset replay_codes_overlay [expr $overidx+1] $cursor_saved_attributes
set cursor_saved_position [dict create]
set cursor_saved_attributes ""
} else {
#TODO
#?restore without save?
#should move to home position and reset ansi SGR?
#puts stderr "overtype::left cursor_restore without save data available"
}
#If we were inserting prior to hitting the cursor_restore - there could be overflow_right data - generally the overtype functions aren't for inserting - but ansi can enable it
#if we were already in overflow when cursor_restore was hit - it shouldn't have been processed as an action - just stored.
if {!$overflow_handled && $overflow_right ne ""} {
#wrap before restore? - possible effect on saved cursor position
#this overflow data has previously been rendered so has no cursor movements or further save/restore operations etc
#we can just insert another call to renderline to solve this.. ?
#It would perhaps be more properly handled as a queue of instructions from our initial renderline call
#we don't need to worry about overflow next call- but we should carry forward our gx and ansi stacks
set blank [string repeat " " [punk::ansi::printing_length $overflow_right]] ;#use size of rendered overflow rather than colwidth which would add trailing space
set foldline [overtype::renderline $blank $overflow_right]
linsert outputlines $renderedrow $foldline
#review - row & col set by restore - but not if there was no save..
}
set overflow_handled 1
} else {
#todo - handle potential insertion mode as above for cursor restore? #todo - handle potential insertion mode as above for cursor restore?
#keeping separate branches for debugging - review and merge as appropriate when stable #keeping separate branches for debugging - review and merge as appropriate when stable
switch -- $instruction { switch -- $instruction {
"" { {} {
if {$unapplied eq ""} { flush stdout
if {$unapplied eq "" && [ansistring length $rendered]} {
#consumed all overlay - no instruction #consumed all overlay - no instruction
set col 1 set col 1
incr row incr row
@ -436,79 +421,138 @@ proc overtype::left {args} {
} }
} }
up { up {
#renderline already knows not to go above l
#renderline knows it's own line number, and knows not to go above row l
#it knows that a move whilst 1-beyond the width conflicts with the linefeed and reduces the move by one accordingly.
#row returned should be correct.
#column may be the overflow column - as it likes to report that to the caller.
#Note that an ansi up sequence after last column going up to a previous line and also beyond the last column, will result in the next grapheme going onto the following line. #Note that an ansi up sequence after last column going up to a previous line and also beyond the last column, will result in the next grapheme going onto the following line.
#this seems correct - as the column remains beyond the right margin so subsequent chars wrap (?) review #this seems correct - as the column remains beyond the right margin so subsequent chars wrap (?) review
#puts stderr "up $post_render_row" #puts stderr "up $post_render_row"
#puts stderr "$rinfo" #puts stderr "$rinfo"
#puts stdout "1 row:$row col $col"
set row $post_render_row set row $post_render_row
set rowdata [lindex $outputlines [expr {$row -1}]] set col $post_render_col
set len [punk::ansi::printing_length $rowdata]
if {$len+1 < $post_render_col} { #puts stdout "2 row:$row col $col"
set col [expr {$len+1}] #puts stdout "-----------------------"
} else { #puts stdout $rinfo
set col $post_render_col #flush stdout
}
} }
down { down {
#renderline doesn't know how far down we can go.. #renderline doesn't know how far down we can go..
if {$post_render_row > [llength $outputlines]} { if {$post_render_row > [llength $outputlines]} {
#if {$opt_appendlines} { if {$opt_appendlines} {
# set diff [expr {$post_render_row - [llength $outputlines]}] set diff [expr {$post_render_row - [llength $outputlines]}]
# if {$diff > 0} { if {$diff > 0} {
# lappend outputlines {*}[lrepeat $diff ""] lappend outputlines {*}[lrepeat $diff ""]
# } }
#} lappend outputlines ""
set row [llength $outputlines] }
} else {
set row $post_render_row
} }
set row $post_render_row
set col $post_render_col set col $post_render_col
} }
restore_cursor {
#testfile belinda.ans uses this
#puts stdout "[a+ blue bold]CURSOR_RESTORE[a]"
if {[dict exists $cursor_saved_position row]} {
set row [dict get $cursor_saved_position row]
set col [dict get $cursor_saved_position column]
#puts stdout "restoring: row $row col $col [ansistring VIEW $cursor_saved_attributes] [a] unapplied [ansistring VIEWCODES $unapplied]"
#set nextprefix $cursor_saved_attributes
lset replay_codes_overlay [expr $overidx+1] $cursor_saved_attributes
set cursor_saved_position [dict create]
set cursor_saved_attributes ""
} else {
#TODO
#?restore without save?
#should move to home position and reset ansi SGR?
#puts stderr "overtype::left cursor_restore without save data available"
}
#If we were inserting prior to hitting the cursor_restore - there could be overflow_right data - generally the overtype functions aren't for inserting - but ansi can enable it
#if we were already in overflow when cursor_restore was hit - it shouldn't have been processed as an action - just stored.
if {!$overflow_handled && $overflow_right ne ""} {
#wrap before restore? - possible effect on saved cursor position
#this overflow data has previously been rendered so has no cursor movements or further save/restore operations etc
#we can just insert another call to renderline to solve this.. ?
#It would perhaps be more properly handled as a queue of instructions from our initial renderline call
#we don't need to worry about overflow next call (?)- but we should carry forward our gx and ansi stacks
set sub_info [overtype::renderline -info 1 -width $colwidth -insert_mode $insert_mode -autowrap_mode $autowrap_mode -overflow [dict get $opts -overflow] "" $overflow_right]
set foldline [dict get $sub_info result]
set insert_mode [dict get $sub_info insert_mode] ;#probably not needed..
set autowrap_mode [dict get $sub_info autowrap_mode] ;#nor this..
linsert outputlines $renderedrow $foldline
#review - row & col set by restore - but not if there was no save..
}
set overflow_handled 1
}
move { move {
########
#Ansi moves need to create new lines
if {$post_render_row > [llength $outputlines]} { if {$post_render_row > [llength $outputlines]} {
set row [llength $outputlines] if {$opt_appendlines} {
set diff [expr {$post_render_row - [llength $outputlines]}]
if {$diff > 0} {
lappend outputlines {*}[lrepeat $diff ""]
}
set row $post_render_row
} else {
set row [llength $outputlines]
}
} else { } else {
set row $post_render_row set row $post_render_row
} }
#######
set col $post_render_col set col $post_render_col
#overflow + unapplied? #overflow + unapplied?
} }
newline_above - newline_below { newlines_above {
#todo #renderline doesn't advance the row for us - the caller has the choice to implement or not
set row $post_render_row
set col $post_render_col
if {$new_lines_above > 0} {
set outputlines [linsert $outputlines $row [lrepeat $new_lines_above ""]]
incr row $new_lines_above ;#we should end up on the same line of text (at a different index), with new empties inserted above
}
}
newlines_below {
puts newlines_below
} }
wrap { wrapmoveforward {
#hard wraps in this context. #doesn't seem to be used by fruit.ans testfile
#used by dzds.ans
#note that cursor_forward may move deep into the next line - or even span multiple lines !TODO #note that cursor_forward may move deep into the next line - or even span multiple lines !TODO
if {$overflow_right_column eq ""} { set c $colwidth
#so why are we getting a wrap instruction? set r $post_render_row
puts stderr "overtype::left wrap instruction when no overflow_right_column\n$rinfo" if {$post_render_col > $colwidth} {
incr row set i $c
set col 1 while {$i <= $post_render_col} {
} else { if {$c == $colwidth+1} {
if {$post_render_col >= $overflow_right_column} { incr r
#review - check printing_length of each following underlay line and move appropriately? if {$opt_appendlines} {
#puts "post_render_col: $post_render_col" if {$r < [llength $outputlines]} {
#puts "overflow_right_column: $overflow_right_column" lappend outputlines ""
set c $overflow_right_column }
set i $c }
while {$i <= $post_render_col} { set c 1
if {($i-1) % $colwidth == 0} { } else {
incr row incr c
set c 1 }
} else { incr i
incr c
}
incr i
}
set col $c
#incr row
#set col [expr {1+ ($post_render_col - $overflow_right_column)}]
} else {
incr row
set col 1
} }
set col $c
} else {
set r [expr {$post_render_row +1}]
set c $post_render_col
} }
set row $r
set col $c
} }
overflow { overflow {
#normal single-width grapheme overflow #normal single-width grapheme overflow
@ -517,7 +561,7 @@ proc overtype::left {args} {
if {!$autowrap_mode} { if {!$autowrap_mode} {
set overflow_handled 1 set overflow_handled 1
set unapplied "" set unapplied ""
#handled by dropping it.. #handled by dropping it
} }
} }
overflow_splitchar { overflow_splitchar {
@ -528,10 +572,11 @@ proc overtype::left {args} {
set col 1 set col 1
} else { } else {
set overflow_handled 1 set overflow_handled 1
#handled by dropping it.. #handled by dropping it
} }
} }
vt { vt {
#can vt add a line like a linefeed can? #can vt add a line like a linefeed can?
set row $post_render_row set row $post_render_row
set col $post_render_col set col $post_render_col
@ -541,15 +586,12 @@ proc overtype::left {args} {
} }
} }
}
if {!$overflow_handled} { if {!$overflow_handled} {
append nextprefix $overflow_right append nextprefix $overflow_right
} }
append nextprefix $unapplied append nextprefix $unapplied
#if {$instruction ne ""} {
# puts "---->>instruction:'$instruction' nextprefix:[ansistring VIEW $nextprefix]<<---"
#}
if {$nextprefix ne ""} { if {$nextprefix ne ""} {
set nextoveridx [expr {$overidx+1}] set nextoveridx [expr {$overidx+1}]
if {$nextoveridx >= [llength $overlines]} { if {$nextoveridx >= [llength $overlines]} {
@ -566,6 +608,7 @@ proc overtype::left {args} {
#lset replay_codes_overlay [expr $overidx+1] [dict get $rinfo replay_codes_overlay] #lset replay_codes_overlay [expr $overidx+1] [dict get $rinfo replay_codes_overlay]
set prevrow $renderedrow set prevrow $renderedrow
incr overidx
} }
#puts stdout $underlay_resets #puts stdout $underlay_resets
return [join $outputlines \n] return [join $outputlines \n]
@ -906,13 +949,37 @@ proc overtype::grapheme_width_cached {ch} {
return $width return $width
} }
#v2
#-returnextra to enable returning of overflow and length
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
#
#
#-returnextra enables returning of overflow and length
#review - use punk::ansi::ta::detect to short-circuit processing and do simpler string calcs as an optimisation? #review - use punk::ansi::ta::detect to short-circuit processing and do simpler string calcs as an optimisation?
#review - DECSWL/DECDWL double width line codes - very difficult/impossible to align and compose with other elements #review - DECSWL/DECDWL double width line codes - very difficult/impossible to align and compose with other elements
#(could render it by faking it with sixels and a lot of work - find/make a sixel font and ensure it's exactly 2 cols per char)
#todo - review transparency issues with single/double width characters #todo - review transparency issues with single/double width characters
#bidi - need a base direction and concept of directional runs for RTL vs LTR - may be best handled at another layer? #bidi - need a base direction and concept of directional runs for RTL vs LTR - may be best handled at another layer?
proc overtype::renderline {args} { proc overtype::renderline {args} {
#*** !doctools
#[call [fun overtype::renderline] [arg args] ]
#[para] renderline is the core engine for overtype string processing (frames & textblocks), and the raw mode commandline repl for the Tcl Punk Shell
#[para] It is also a central part of an ansi (micro) virtual terminal-emulator of sorts
#[para] This system does a half decent job at rendering 90's ANSI art to manipulable colour text blocks that can be joined & framed for layout display within a unix or windows terminal
#[para] Renderline helps maintain ANSI text styling reset/replay codes so that the styling of one block doesn't affect another.
#[para] Calling on the punk::ansi library - it can coalesce codes to keep the size down.
#[para] It is a giant mess of doing exactly what common wisdom says not to do... lots at once.
#[para] renderline is part of the Unicode and ANSI aware Overtype system which 'renders' a block of text onto a static underlay
#[para] The underlay is generally expected to be an ordered set of lines or a rectangular text block analogous to a terminal screen - but it can also be ragged in line length, or just blank.
#[para] The overlay couuld be similar - in which case it may often be used to overwrite a column or section of the underlay.
#[para] The overlay could however be a sequence of ANSI-laden text that jumps all over the place.
#
#[para] renderline itself only deals with a single line - or sometimes a single character. It is generally called from a loop that does further terminal-like or textblock processing.
#[para] By suppyling the -info 1 option - it can return various fields indicating the state of the render.
#[para] The main 3 are the result, overflow_right, and unapplied.
#[para] Renderline handles cursor movements from either keystrokes or ANSI sequences but for a full system the aforementioned loop will need to be in place to manage the set of lines under manipulation.
if {[llength $args] < 2} { if {[llength $args] < 2} {
error {usage: ?-info 0|1? ?-startcolumn <int>? ?-cursor_column <int>? ?-cursor_row <int>|""? ?-transparent [0|1|<regexp>]? ?-overflow [1|0]? undertext overtext} error {usage: ?-info 0|1? ?-startcolumn <int>? ?-cursor_column <int>? ?-cursor_row <int>|""? ?-transparent [0|1|<regexp>]? ?-overflow [1|0]? undertext overtext}
} }
@ -1053,7 +1120,9 @@ proc overtype::renderline {args} {
#an ugly hack to serve *some* common case ascii quickly with byte-compiled literal switch - feels dirty. #an ugly hack to serve *some* common case ascii quickly with byte-compiled literal switch - feels dirty.
#.. but even 0.5uS per char (grapheme_width_cached) adds up quickly when stitching lots of lines together. #.. but even 0.5uS per char (grapheme_width_cached) adds up quickly when stitching lots of lines together.
switch -- $grapheme { switch -- $grapheme {
" " - - - _ - ! - @ - # - $ - % - ^ - & - * - = - + - : - . - , - / - | - ? - a - b - c - d - e - f - g - h - i - j - k - l - m - n - o - p - q - r - s - t - u - v - w - x - y - z - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 { " " - - - _ - ! - @ - # - $ - % - ^ - & - * - = - + - : - . - , - / - | - ? -
a - b - c - d - e - f - g - h - i - j - k - l - m - n - o - p - q - r - s - t - u - v - w - x - y -
z - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 {
set width 1 set width 1
} }
default { default {
@ -1102,11 +1171,12 @@ proc overtype::renderline {args} {
} }
} }
} }
#consider also if there are other codes that should be stacked..? #consider also if there are other codes that should be stacked..?
} }
#fill columns to width with spaces, and carry over stacks - we will have to keep track of where the underlying data ends manually - TODO #fill columns to width with spaces, and carry over stacks - we will have to keep track of where the underlying data ends manually - TODO
if {$opt_width ne "\uFFef"} { if {$opt_width ne "\uFFEf"} {
if {[llength $understacks]} { if {[llength $understacks]} {
set cs $u_codestack set cs $u_codestack
set gs $u_gx_stack set gs $u_gx_stack
@ -1287,7 +1357,7 @@ proc overtype::renderline {args} {
for {set gci 0} {$gci < [llength $overlay_grapheme_control_list]} {incr gci} { for {set gci 0} {$gci < [llength $overlay_grapheme_control_list]} {incr gci} {
set gc [lindex $overlay_grapheme_control_list $gci] set gc [lindex $overlay_grapheme_control_list $gci]
lassign $gc type item lassign $gc type item
#emit plaintext chars first using existing SGR codes from under/over stack as appropriate #emit plaintext chars first using existing SGR codes from under/over stack as appropriate
#then check if the following code is a cursor movement within the line and adjust index if so #then check if the following code is a cursor movement within the line and adjust index if so
#foreach ch $overlay_graphemes {} #foreach ch $overlay_graphemes {}
@ -1295,8 +1365,17 @@ proc overtype::renderline {args} {
g { g {
set ch $item set ch $item
incr idx_over; #idx_over (until unapplied reached anyway) is per *grapheme* in the overlay - not per col. incr idx_over; #idx_over (until unapplied reached anyway) is per *grapheme* in the overlay - not per col.
set within_undercols [expr {$idx <= [llength $undercols]-1}] ;#within our original data width if {$overflow_idx == -1} {
#review.
#This corresponds to opt_overflow being ture (at least until overflow_idx is in some cases forced to a value when throwing back to calling loop)
set within_undercols false
if {$idx <= [llength $undercols]-1 && [llength $undercols]} {
set within_undercols true
}
} else {
set within_undercols [expr {$idx <= [llength $undercols]-1}] ;#within our active data width
}
if {$overflow_idx != -1} { if {$overflow_idx != -1} {
@ -1406,24 +1485,50 @@ proc overtype::renderline {args} {
set chtest [string map [list \n <lf> \b <bs> \r <cr> \v <vt> \x7f <del>] $ch] set chtest [string map [list \n <lf> \b <bs> \r <cr> \v <vt> \x7f <del>] $ch]
switch -- $chtest { switch -- $chtest {
"<lf>" { "<lf>" {
incr cursor_row if 1 {
#override overflow_idx even if it was set to -1 due to opt_overflow = 1|2
set overflow_idx $idx if {$idx == 0} {
#idx_over already incremented #leave the overflow_idx
priv::render_unapplied $overlay_grapheme_control_list $gci set insert_lines_above 1 ;#keep for consistency with ansi sequence that requests insertion of line(s)?
set instruction newlines_above
} else {
#linefeed occurred in middle or at end of text
incr cursor_row
#override overflow_idx even if it was set to -1 due to opt_overflow = 1|2
set overflow_idx $idx
set insert_lines_below 1
set instruction newlines_below
}
#idx_over already incremented
priv::render_unapplied $overlay_grapheme_control_list $gci
break
if {$idx == 0} {
set insert_lines_above 1 ;#keep for consistency with ansi sequence that requests insertion of line(s)?
set instruction newline_above
} else { } else {
set insert_lines_below 1 #v1
set instruction newline_below incr cursor_row
#override overflow_idx even if it was set to -1 due to opt_overflow = 1|2
set overflow_idx $idx
#idx_over already incremented
priv::render_unapplied $overlay_grapheme_control_list $gci
if {$idx == 0} {
set insert_lines_above 1 ;#keep for consistency with ansi sequence that requests insertion of line(s)?
set instruction newlines_above
} else {
set insert_lines_below 1
set instruction newlines_below
}
break
} }
break
#set cursor_column 1
} }
"<cr>" { "<cr>" {
#consider also the old space-carriagereturn softwrap convention used in some terminals.
#In the context of rendering to a block of text - this works similarly in that the space gets eaten so programs emitting space-cr at the terminal width col will pretty much get what they expect.
set idx [expr {$opt_colstart -1}] set idx [expr {$opt_colstart -1}]
set cursor_column $opt_colstart ;#? set cursor_column $opt_colstart ;#?
} }
@ -1478,7 +1583,6 @@ proc overtype::renderline {args} {
priv::render_addchar [expr {$idx-1}] $opt_exposed1 [lindex $understacks $idx-1] [lindex $understacks_gx $idx-1] 0 priv::render_addchar [expr {$idx-1}] $opt_exposed1 [lindex $understacks $idx-1] [lindex $understacks_gx $idx-1] 0
} }
incr idx incr idx
incr cursor_column
} else { } else {
set prevcolinfo [lindex $outcols $idx-1] set prevcolinfo [lindex $outcols $idx-1]
#for insert mode - first replace the empty 2ndhalf char with exposed2 before shifting it right #for insert mode - first replace the empty 2ndhalf char with exposed2 before shifting it right
@ -1494,9 +1598,10 @@ proc overtype::renderline {args} {
priv::render_addchar [expr {$idx-1}] $opt_exposed1 [lindex $understacks $idx-1] [lindex $understacks_gx $idx-1] 0 ;#replace not insert priv::render_addchar [expr {$idx-1}] $opt_exposed1 [lindex $understacks $idx-1] [lindex $understacks_gx $idx-1] 0 ;#replace not insert
} ;# else?? } ;# else??
incr idx incr idx
}
if {$cursor_column < [llength $outcols] || $overflow_idx == -1} {
incr cursor_column incr cursor_column
} }
} elseif {$uwidth == 0} { } elseif {$uwidth == 0} {
if {$within_undercols} { if {$within_undercols} {
#e.g combining diacritic - increment before over char REVIEW #e.g combining diacritic - increment before over char REVIEW
@ -1512,12 +1617,14 @@ proc overtype::renderline {args} {
incr idx incr idx
incr cursor_column incr cursor_column
} }
if {$cursor_column > [llength $outcols]} {
set cursor_column [llength $outcols]
}
} elseif {$uwidth == 1} { } elseif {$uwidth == 1} {
set owidth [grapheme_width_cached $ch] set owidth [grapheme_width_cached $ch]
if {$owidth == 1} { if {$owidth == 1} {
priv::render_addchar $idx $ch [lindex $overstacks $idx_over] [lindex $overstacks_gx $idx_over] $insert_mode priv::render_addchar $idx $ch [lindex $overstacks $idx_over] [lindex $overstacks_gx $idx_over] $insert_mode
incr idx incr idx
incr cursor_column
} else { } else {
priv::render_addchar $idx $ch [lindex $overstacks $idx_over] [lindex $overstacks_gx $idx_over] $insert_mode priv::render_addchar $idx $ch [lindex $overstacks $idx_over] [lindex $overstacks_gx $idx_over] $insert_mode
incr idx incr idx
@ -1528,6 +1635,8 @@ proc overtype::renderline {args} {
priv::render_addchar [expr {$idx+1}] $opt_exposed2 [lindex $understacks $idx+1] [lindex $understacks_gx $idx+1] $insert_mode priv::render_addchar [expr {$idx+1}] $opt_exposed2 [lindex $understacks $idx+1] [lindex $understacks_gx $idx+1] $insert_mode
} }
incr idx incr idx
}
if {($cursor_column < [llength $outcols]) || $overflow_idx == -1} {
incr cursor_column incr cursor_column
} }
} elseif {$uwidth > 1} { } elseif {$uwidth > 1} {
@ -1552,6 +1661,9 @@ proc overtype::renderline {args} {
incr idx 2 incr idx 2
incr cursor_column 2 incr cursor_column 2
} }
if {$cursor_column > [llength $outcols] || $overflow_idx == -1} {
set cursor_column [llength $outcols]
}
} }
} }
} ;# end switch } ;# end switch
@ -1604,22 +1716,27 @@ proc overtype::renderline {args} {
set version 2 set version 2
if {$version eq "2"} { if {$version eq "2"} {
set max [llength $outcols] set max [llength $outcols]
if {$opt_overflow} { if {$overflow_idx == -1} {
incr max incr max
} }
if {($cursor_column + $num) <= $max} { if {($cursor_column + $num) <= $max} {
incr idx $num incr idx $num
incr cursor_column $num incr cursor_column $num
} else { } else {
if {$opt_autowrap_mode} { if {$opt_autowrap_mode} {
if {$idx == $overflow_idx} {
incr num
}
#horizontal movement beyond line extent needs to wrap - throw back to caller #horizontal movement beyond line extent needs to wrap - throw back to caller
#we may have both overflow_rightand unapplied data #we may have both overflow_rightand unapplied data
#(can have overflow_right if we were in insert_mode and processed chars prior to this movement) #(can have overflow_right if we were in insert_mode and processed chars prior to this movement)
#leave row as is - caller will need to determine how many rows the column-movement has consumed #leave row as is - caller will need to determine how many rows the column-movement has consumed
incr cursor_column $num ;#give our caller the necessary info incr cursor_column $num ;#give our caller the necessary info as columns from start of row
incr idx_over #incr idx_over
#should be gci following last one applied
priv::render_unapplied $overlay_grapheme_control_list $gci priv::render_unapplied $overlay_grapheme_control_list $gci
set instruction wrap set instruction wrapmoveforward
break break
} else { } else {
set cursor_column $max set cursor_column $max
@ -1695,9 +1812,16 @@ proc overtype::renderline {args} {
if {$num eq ""} {set num 1} if {$num eq ""} {set num 1}
incr cursor_row -$num incr cursor_row -$num
#if {$overflow_idx != -1} {
# if {$idx == $overflow_idx} {
# #compensate for linefeed
# incr cursor_row
# }
#}
if {$cursor_row < 1} { if {$cursor_row < 1} {
set cursor_row 1 set cursor_row 1
} }
#ensure rest of *overlay* is emitted to remainder #ensure rest of *overlay* is emitted to remainder
incr idx_over incr idx_over
priv::render_unapplied $overlay_grapheme_control_list $gci priv::render_unapplied $overlay_grapheme_control_list $gci
@ -1706,9 +1830,23 @@ proc overtype::renderline {args} {
break break
} }
B { B {
set row_before_move $cursor_row
#move down #move down
if {$num eq ""} {set num 1} if {$num eq ""} {set num 1}
incr cursor_row $num incr cursor_row $num
#if {$overflow_idx != -1} {
# if {$idx == $overflow_idx} {
# #incr cursor_row -1
# if {$cursor_row == $row_before_move} {
# if {!$opt_overflow} {
# #allow other controls to be processed or next grapheme to overflow
# continue
# }
# }
# }
#}
incr idx_over ;#idx_over hasn't encountered a grapheme and hasn't advanced yet incr idx_over ;#idx_over hasn't encountered a grapheme and hasn't advanced yet
priv::render_unapplied $overlay_grapheme_control_list $gci priv::render_unapplied $overlay_grapheme_control_list $gci
set instruction down set instruction down
@ -1722,7 +1860,7 @@ proc overtype::renderline {args} {
if {$col eq ""} {set col 1} if {$col eq ""} {set col 1}
set max [llength $outcols] set max [llength $outcols]
if {$opt_overflow} { if {$overflow_idx == -1} {
incr max incr max
} }
if {$col > $max} { if {$col > $max} {
@ -1818,9 +1956,13 @@ proc overtype::renderline {args} {
#a real terminal would not be able to know the state of the underlay.. so we should probably ignore it. #a real terminal would not be able to know the state of the underlay.. so we should probably ignore it.
#set sgr_stack [lindex $understacks $idx] #set sgr_stack [lindex $understacks $idx]
#set gx_stack [lindex $understacks_gx $idx] ;#not actually a stack - just a boolean state (for now?) #set gx_stack [lindex $understacks_gx $idx] ;#not actually a stack - just a boolean state (for now?)
set sgr_stack [list] set sgr_stack [list]
set gx_stack [list] set gx_stack [list]
#we shouldn't need to scan for intermediate cursor save/restores - as restores would throw-back to the calling loop - so our overlay 'line' is since those.
#The overlay_grapheme_control_list had leading resets from previous lines - so we go back to the beginning not just the first grapheme.
foreach gc [lrange $overlay_grapheme_control_list 0 $gci-1] { foreach gc [lrange $overlay_grapheme_control_list 0 $gci-1] {
lassign $gc type code lassign $gc type code
#types g other sgr gx0 #types g other sgr gx0
@ -1859,25 +2001,7 @@ proc overtype::renderline {args} {
#append cursor_saved_attributes [join $sgr_stack ""] #append cursor_saved_attributes [join $sgr_stack ""]
append cursor_saved_attributes [punk::ansi::codetype::sgr_merge_list {*}$sgr_stack] append cursor_saved_attributes [punk::ansi::codetype::sgr_merge_list {*}$sgr_stack]
#as there is apparently only one cursor storage element we don't need to throw back to the calling loop for a save.
if 0 {
set stack_cur [join [lindex $understacks $idx] ""]
set stack_prev [join [lindex $understacks $idx-1] ""]
puts ">>>'[ansistring VIEW $stack_cur]' prev:'[ansistring VIEW $stack_prev]'"
puts "idx_over: $idx_over"
set cursor_saved_attributes $stack_prev
switch -- [lindex $understacks_gx $idx] {
"gx0_on" {
append cursor_saved_attributes "\x1b(0"
}
"gx0_off" {
append cursor_saved_attributes "\x1b(B"
}
}
}
#don't incr index - or the save will cause cursor to move to the right #don't incr index - or the save will cause cursor to move to the right
#carry on #carry on
@ -1909,9 +2033,9 @@ proc overtype::renderline {args} {
#incr idx_over #incr idx_over
} }
#if the save occured within this line - that's ok - it's in the return value list and caller can prepend for the next loop.
set instruction move set instruction restore_cursor
set cursor_restore_required 1
break break
}\ }\
$re_mode { $re_mode {
@ -2111,7 +2235,6 @@ proc overtype::renderline {args} {
insert_lines_below $insert_lines_below\ insert_lines_below $insert_lines_below\
cursor_saved_position $cursor_saved_position\ cursor_saved_position $cursor_saved_position\
cursor_saved_attributes $cursor_saved_attributes\ cursor_saved_attributes $cursor_saved_attributes\
cursor_restore_required $cursor_restore_required\
cursor_column $cursor_column\ cursor_column $cursor_column\
cursor_row $cursor_row\ cursor_row $cursor_row\
opt_overflow $opt_overflow\ opt_overflow $opt_overflow\

2401
src/vendormodules/overtype-1.6.0.tm

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save