Browse Source

ansi fixes - cursor movement

master
Julian Noble 10 months ago
parent
commit
c29cf8b146
  1. 153
      src/modules/punk/ansi-999999.0a1.0.tm
  2. 2
      src/modules/punk/lib-999999.0a1.0.tm
  3. 5
      src/modules/punk/repl-0.1.tm
  4. 831
      src/vendormodules/overtype-1.5.9.tm

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

@ -95,7 +95,11 @@ namespace eval punk::ansi::class {
}
if {$o_rendered_what ne $o_raw || $dimensions ne $o_render_dimensions} {
set b [textblock::block $w $h " "]
#some ansi art/layout relies on wrapping at the width-dimension to display properly
#some ansi layout/art relies on wrapping at the width-dimension to display properly
#this includes cursor movements ie right arrow can move cursor to columns in lines below
#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 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_what $o_raw
set o_render_dimensions $dimensions
@ -113,6 +117,9 @@ namespace eval punk::ansi::class {
method viewchars {} {
return [punk::ansi::stripansiraw $o_raw]
}
method viewstyle {} {
return [ansistring VIEWSTYLE $o_raw]
}
}
}
@ -175,21 +182,47 @@ namespace eval punk::ansi {
#review - We have file possibly encoded directly in another codepage such as 437 - or utf8,utf16 etc, but then still needing post conversion to e.g cp437?
proc readfile {fname} {
proc readfile {fname {encoding cp437}} {
#todo
#1- look for BOM - read according to format given by BOM
#2- assume utf-8
#3- if errors - assume cp437?
set data [fcat $fname]
if {[file extension $fname] eq ".ans"} {
set ansidata [encoding convertfrom cp437 $data]
} else {
set ansidata $data
}
set ansidata [fcat -encoding $encoding $fname]
set obj [punk::ansi::class::class_ansi new $ansidata]
return $obj
}
proc ansicat {fname args} {
set encnames [encoding names]
set encoding ""
set dimensions ""
foreach a $args {
if {$a in $encnames} {
set encoding $a
} else {
if {[regexp {[0-9]+(?:x|X)[0-9]+} $a]} {
set dimensions $a
}
}
}
if {$encoding eq ""} {
set encoding cp437
}
if {$dimensions eq ""} {
set dimensions 80x26
}
set ansidata [fcat -encoding $encoding $fname]
set obj [punk::ansi::class::class_ansi new $ansidata]
$obj render $dimensions
}
#utf-8/ascii encoded cp437
proc ansicat2 {fname {encoding utf-8}} {
set data [fcat -encoding $encoding $fname]
set ansidata [encoding convertfrom cp437 $data]
set obj [punk::ansi::class::class_ansi new $ansidata]
$obj render
}
proc is_utf8_char {char} {
regexp {(?x) # Expanded regexp syntax, so I can put in comments :-)
[\x00-\x7F] | # Single-byte chars (ASCII range)
@ -931,8 +964,47 @@ namespace eval punk::ansi {
#[para] DECRC
return \x1b8
}
# -- --- --- --- ---
#DECAWM - automatic line wrapping
proc enable_line_wrap {} {
#*** !doctools
#[call [fun enable_line_wrap]]
#[para] enable automatic line wrapping when characters entered beyond rightmost column
#[para] This will also allow forward movements to move to subsequent lines
#[para] This is DECAWM - and is the same sequence output by 'tput smam'
return \x1b\[?7h
}
proc disable_line_wrap {} {
#*** !doctools
#[call [fun disable_line_wrap]]
#[para] disable automatic line wrapping
#[para] reset DECAWM - same sequence output by 'tput rmam'
#tput rmam
return \x1b\[?7l
}
#DECRQM to query line-wrap state
# \x1b\[?7\$p
#DECRPM responses e.g:
# \x1b\[?7\;1\$y
# \x1b\[?7\;2\$y
#where 1 = set, 2 = unset. (0 = mode not recognised, 3 = permanently set, 4 = permanently unset)
#Alt screen buffer
proc enable_alt_screen {} {
#tput smcup outputs "\x1b\[?1049h\x1b\[22\;0\;0t" second esc sequence - DECSLPP? setting page height one less than main screen?
#\x1b\[?1049h ;#xterm
return \x1b\[?47h
}
proc disable_alt_screen {} {
#tput rmcup outputs \x1b\[?1049l\x1b\[23\;0\;0t]
#\x1b\[?1049l
return \x1b\[?47l
}
# -- --- ---
proc erase_line {} {
#*** !doctools
#[call [fun erase_line]]
@ -1334,14 +1406,17 @@ namespace eval punk::ansi {
dict set codestate_empty nosupersub "" ;#75
# --
dict set codestate_empty fgbright "" ;#90-97 - keeping separate to fg ie unmerged with it. unsure how it interacts or is used. REVIEW.
dict set codestate_empty bgbright "" ;#100-107 as above
dict set codestate_empty fg ""
dict set codestate_empty bg ""
dict set codestate_empty fg "" ;#30-37 + 90-97
dict set codestate_empty bg "" ;#40-47 + 100-107
proc sgr_merge {args} {
#as a common case optimisation - it will not merge a single element list, even if that code contains redundant elements
proc sgr_merge_list {args} {
if {[llength $args] == 0} {
return ""
} elseif {[llength $args] == 1} {
return [lindex $args 0]
}
variable codestate_empty
set othercodes [list]
@ -1619,11 +1694,10 @@ namespace eval punk::ansi {
dict set codestate subcript ""
}
90 - 91 - 92 - 93 - 94 - 95 - 96 - 97 {
#does this belong with fg? REVIEW
dict set codestate fgbright $p
dict set codestate fg $p
}
100 - 101 - 102 - 103 - 104 - 105 - 106 - 107 {
dict set codestate bgbright $p
dict set codestate bg $p
}
}
@ -1933,7 +2007,7 @@ namespace eval punk::ansi::ansistring {
namespace path [list ::punk::ansi ::punk::ansi::ta]
namespace ensemble create
namespace export length length1 trim trimleft trimright index VIEW VIEWCODES INDEXABSOLUTE INDEXCOLUMNS COLUMNINDEX
namespace export length length1 trim trimleft trimright index VIEW VIEWCODES VIEWSTYLE INDEXABSOLUTE INDEXCOLUMNS COLUMNINDEX
#todo - expose _splits_ methods so caller can work efficiently with the splits themselves
#we need to consider whether these can be agnostic towards splits from split_codes vs split_codes_single
@ -2353,7 +2427,7 @@ namespace eval punk::ansi::ansistring {
switch -regexp -matchvar matchinfo -- $code\
$re_row_move {
set displaycode [ansistring VIEW $code]
set displaycode [string map [list A "C$arrow_up" B "D$arrow_down"] $displaycode]
set displaycode [string map [list A "A$arrow_up" B "B$arrow_down"] $displaycode]
append output ${cyanb}$displaycode$RST
}\
$re_col_move {
@ -2391,6 +2465,45 @@ namespace eval punk::ansi::ansistring {
}
return $output
}
#an attempt to show the codes and colour/style of the *input*
#ie we aren't looking at the row/column positioning - but we do want to keep track of cursor attribute saves and restores
proc VIEWSTYLE {string} {
set splits [punk::ansi::ta::split_codes_single $string]
set output ""
set codestack [list]
set gx_stack [list] ;#not actually a stack
set cursor_saved ""
foreach {pt code} $splits {
append output [punk::ansi::codetype::sgr_merge_list {*}$codestack]$pt
if {$code ne ""} {
append output [a][VIEW $code]
if {[punk::ansi::codetype::is_sgr_reset $code]} {
set codestack [list]
} elseif {[punk::ansi::codetype::has_sgr_leadingreset $code]} {
set codestack [list $code]
} elseif {[punk::ansi::codetype::is_sgr $code]} {
#basic simplification first.. straight dups
set dup_posns [lsearch -all -exact $codestack $code] ;#-exact because of square-bracket glob chars
set codestack [lremove $codestack {*}$dup_posns]
lappend codestack $code
} elseif {[regexp {\x1b7|\x1b\[s} $code]} {
#cursor_save
set cursor_saved [punk::ansi::codetype::sgr_merge_list {*}$codestack]
} elseif {[regexp {\x1b8|\x1b\[u} $code]} {
#cursor_restore
set codestack [list $cursor_saved]
} else {
#leave SGR stack as is
if {[punk::ansi::codetype::is_gx_open $code]} {
set gx_stack [list gx0_on] ;#we'd better use a placeholder - or debugging will probably get into a big mess
} elseif {[punk::ansi::codetype::is_gx_close $code]} {
set gx_stack [list]
}
}
}
}
return $output
}
proc length {string} {
#*** !doctools

2
src/modules/punk/lib-999999.0a1.0.tm

@ -937,7 +937,7 @@ namespace eval punk::lib {
}
#set newreplay [join $codestack ""]
set newreplay [punk::ansi::codetype::sgr_merge {*}$codestack]
set newreplay [punk::ansi::codetype::sgr_merge_list {*}$codestack]
if {$line_has_sgr && $newreplay ne $replaycodes} {
#adjust if it doesn't already does a reset at start

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

@ -213,6 +213,7 @@ if {$::tcl_platform(platform) eq "windows"} {
#expermental terminal alt screens
#alternatives are \x1b\[?47h ans \x1b[?\47l
proc ::repl::term::screen_push_alt {} {
#tput smcup
puts -nonewline stderr "\033\[?1049h"
@ -1139,7 +1140,7 @@ namespace eval punk::repl::class {
set result [dict get $mergedinfo result]
set o_insert_mode [dict get $mergedinfo insert_mode]
set result_col [dict get $mergedinfo cursor_column]
set cmove [dict get $mergedinfo cursor_row_change]
set cmove [dict get $mergedinfo cursor_row]
set overflow_right [dict get $mergedinfo overflow_right] ;#should be empty if no \v
set unapplied [dict get $mergedinfo unapplied]
set insert_lines_below [dict get $mergedinfo insert_lines_below]
@ -1220,7 +1221,7 @@ namespace eval punk::repl::class {
set result [dict get $mergedinfo result]
set o_insert_mode [dict get $mergedinfo insert_mode]
set o_cursor_col [dict get $mergedinfo cursor_column]
set cmove [dict get $mergedinfo cursor_row_change]
set cmove [dict get $mergedinfo cursor_row]
set overflow_right [dict get $mergedinfo overflow_right] ;#should be empty if no \v
set unapplied [dict get $mergedinfo unapplied]
set insert_lines_below [dict get $mergedinfo insert_lines_below]

831
src/vendormodules/overtype-1.5.9.tm

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