From 4d89217d4a62cb664ac94a78498df5c32141346d Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Thu, 26 Sep 2024 03:01:50 +1000 Subject: [PATCH] work on unix console --- src/modules/punk/console-999999.0a1.0.tm | 8 +++- src/modules/punk/repl-0.1.tm | 44 +++++++++++++++---- .../_vfscommon/modules/punk/console-0.1.1.tm | 8 +++- src/vfs/_vfscommon/modules/punk/repl-0.1.tm | 44 +++++++++++++++---- 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/src/modules/punk/console-999999.0a1.0.tm b/src/modules/punk/console-999999.0a1.0.tm index 72d1ab19..e1fd7d7b 100644 --- a/src/modules/punk/console-999999.0a1.0.tm +++ b/src/modules/punk/console-999999.0a1.0.tm @@ -177,9 +177,13 @@ namespace eval punk::console { } - #todo - something better - the 'channel' concept may not really apply on unix, as raw mode is for input and output modes + #todo - something better - the 'channel' concept may not really apply on unix, as raw mode is set for input and output modes currently - only valid to set on a readable channel? + #on windows they can be set independently (but not with stty) - REVIEW + + #NOTE - the is_raw is only being set in current interp - but the channel is shared. + #this is problematic with the repl thread being separate. - must be a tsv? REVIEW proc enableRaw {{channel stdin}} { - variable is_raw + variable is_raw variable previous_stty_state_$channel set sttycmd [auto_execok stty] if {[set previous_stty_state_$channel] eq ""} { diff --git a/src/modules/punk/repl-0.1.tm b/src/modules/punk/repl-0.1.tm index f40ff65d..48f10610 100644 --- a/src/modules/punk/repl-0.1.tm +++ b/src/modules/punk/repl-0.1.tm @@ -1346,17 +1346,45 @@ proc repl::repl_handler {inputchan prompt_config} { } } else { if {[fblocked $inputchan]} { - #set screeninfo [punk::console::get_size] - #lassign $screeninfo _c cols _r rows - set rows 0 - set cols 3 - if {[string is integer -strict $rows]} { - set RED [punk::ansi::a+ red bold]; set RST [punk::ansi::a] - set msg "${RED}fblocked $inputchan is true. (line-length Tcl windows channel bug?) Hit enter to continue$RST" + #REVIEW - need to und + #todo - figure out why we're here. + #can we even put a spinner so we don't keep emitting lines? We probably can't use any ansi functions that need to get a response on stdin..(like get_cursor_pos) + #punk::console::get_size is problematic if -winsize not available on the stdout channel - which is the case for certain 8.6 versions at least.. platform variances? + ## can't do this: set screeninfo [punk::console::get_size]; lassign $screeninfo _c cols _r rows + set outconf [chan configure stdout] + set RED [punk::ansi::a+ red bold]; set RST [punk::ansi::a] + if {"windows" eq $::tcl_platform(platform)} { + set msg "${RED}$inputchan fblocked is true. (line-length Tcl windows channel bug?)$RST \{$allwaiting\}" + } else { + set msg "${RED}$inputchan fblocked is true.$RST \{$allwaiting\}" + } + set cols "" + set rows "" + if {[dict exists $outconf -winsize]} { + lassign [dict get $outconf -winsize] cols rows + } else { + #fallback - try external executable. Which is a bit ugly + #tput can work on windows too if it's installed e.g from msys2 + #but can be *slow* compared to unix e.g 400ms+ vs <2ms on FreeBSD ! + set tputcmd [auto_execok tput] + if {$tputcmd ne ""} { + if {![catch {exec {*}$tputcmd cols lines} values} { + lassign $values cols rows + } + } + } + if {[string is integer -strict $cols] && [string is integer -strict $rows]} { + #got_dimensions - todo - try spinner? + #puts -nonewline stdout [punk::ansi::move $rows 4]$msg + #use cursorsave_ version which avoids get_cursor_pos_list call + punk::console::cursorsave_move_emitblock_return $rows [expr {$cols - $msglen -1}] $msg + } else { + #no mechanism to get console dimensions + #we are reduced to continuously spewing lines. set msglen [ansistring length $msg] - #punk::console::cursorsave_move_emitblock_return $rows [expr {$cols - $msglen -1}] $msg puts stderr $msg } + after 100 } set input_chunks_waiting($inputchan) [list $allwaiting] diff --git a/src/vfs/_vfscommon/modules/punk/console-0.1.1.tm b/src/vfs/_vfscommon/modules/punk/console-0.1.1.tm index 6f385194..95ecb27d 100644 --- a/src/vfs/_vfscommon/modules/punk/console-0.1.1.tm +++ b/src/vfs/_vfscommon/modules/punk/console-0.1.1.tm @@ -177,9 +177,13 @@ namespace eval punk::console { } - #todo - something better - the 'channel' concept may not really apply on unix, as raw mode is for input and output modes + #todo - something better - the 'channel' concept may not really apply on unix, as raw mode is set for input and output modes currently - only valid to set on a readable channel? + #on windows they can be set independently (but not with stty) - REVIEW + + #NOTE - the is_raw is only being set in current interp - but the channel is shared. + #this is problematic with the repl thread being separate. - must be a tsv? REVIEW proc enableRaw {{channel stdin}} { - variable is_raw + variable is_raw variable previous_stty_state_$channel set sttycmd [auto_execok stty] if {[set previous_stty_state_$channel] eq ""} { diff --git a/src/vfs/_vfscommon/modules/punk/repl-0.1.tm b/src/vfs/_vfscommon/modules/punk/repl-0.1.tm index f40ff65d..48f10610 100644 --- a/src/vfs/_vfscommon/modules/punk/repl-0.1.tm +++ b/src/vfs/_vfscommon/modules/punk/repl-0.1.tm @@ -1346,17 +1346,45 @@ proc repl::repl_handler {inputchan prompt_config} { } } else { if {[fblocked $inputchan]} { - #set screeninfo [punk::console::get_size] - #lassign $screeninfo _c cols _r rows - set rows 0 - set cols 3 - if {[string is integer -strict $rows]} { - set RED [punk::ansi::a+ red bold]; set RST [punk::ansi::a] - set msg "${RED}fblocked $inputchan is true. (line-length Tcl windows channel bug?) Hit enter to continue$RST" + #REVIEW - need to und + #todo - figure out why we're here. + #can we even put a spinner so we don't keep emitting lines? We probably can't use any ansi functions that need to get a response on stdin..(like get_cursor_pos) + #punk::console::get_size is problematic if -winsize not available on the stdout channel - which is the case for certain 8.6 versions at least.. platform variances? + ## can't do this: set screeninfo [punk::console::get_size]; lassign $screeninfo _c cols _r rows + set outconf [chan configure stdout] + set RED [punk::ansi::a+ red bold]; set RST [punk::ansi::a] + if {"windows" eq $::tcl_platform(platform)} { + set msg "${RED}$inputchan fblocked is true. (line-length Tcl windows channel bug?)$RST \{$allwaiting\}" + } else { + set msg "${RED}$inputchan fblocked is true.$RST \{$allwaiting\}" + } + set cols "" + set rows "" + if {[dict exists $outconf -winsize]} { + lassign [dict get $outconf -winsize] cols rows + } else { + #fallback - try external executable. Which is a bit ugly + #tput can work on windows too if it's installed e.g from msys2 + #but can be *slow* compared to unix e.g 400ms+ vs <2ms on FreeBSD ! + set tputcmd [auto_execok tput] + if {$tputcmd ne ""} { + if {![catch {exec {*}$tputcmd cols lines} values} { + lassign $values cols rows + } + } + } + if {[string is integer -strict $cols] && [string is integer -strict $rows]} { + #got_dimensions - todo - try spinner? + #puts -nonewline stdout [punk::ansi::move $rows 4]$msg + #use cursorsave_ version which avoids get_cursor_pos_list call + punk::console::cursorsave_move_emitblock_return $rows [expr {$cols - $msglen -1}] $msg + } else { + #no mechanism to get console dimensions + #we are reduced to continuously spewing lines. set msglen [ansistring length $msg] - #punk::console::cursorsave_move_emitblock_return $rows [expr {$cols - $msglen -1}] $msg puts stderr $msg } + after 100 } set input_chunks_waiting($inputchan) [list $allwaiting]