diff options
Diffstat (limited to 'tcllib/modules/term')
26 files changed, 2845 insertions, 0 deletions
diff --git a/tcllib/modules/term/ChangeLog b/tcllib/modules/term/ChangeLog new file mode 100644 index 0000000..02d5f11 --- /dev/null +++ b/tcllib/modules/term/ChangeLog @@ -0,0 +1,164 @@ +2013-11-22 Andreas Kupries <andreask@activestate.com> + + * ansi/send.tcl: Revert Tcl 8.5 dependency introduced by an + unlogged rewrite [c80b6fffde]. + +2013-11-20 PoorYorick + + * ansi/code.tcl: Unlogged rewrite, with commit message: + * ansi/code/ctrl.tcl: add support for default arguments to + * ansi/send.tcl: term::ansi::send fix documentation types + * ansi_ctrlu.tcl: quoting cleanup + +2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.15 ======================== + * + +2013-01-08 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * ansi/code/ctrl.tcl: Bumped to version 0.1.2. Moved character + definition around to prevent mis-interpretation as a bad + continuation line by static syntax checkers. + +2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.14 ======================== + * + +2011-05-20 Andreas Kupries <andreask@activestate.com> + + * ansi/ctrlunix.tcl (::term::ansi::ctrl::unix::INIT): Modified to + explictly avoid Solaris' /usr/ucb/stty. Its command line syntax + does not fit our expecations. Bumped version to 0.1.1 + +2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.13 ======================== + * + +2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.12 ======================== + * + +2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11.1 ======================== + * + +2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11 ======================== + * + +2008-03-14 Andreas Kupries <andreask@activestate.com> + + * ansi/code/ctrl.tcl (DEFC): Fixed bad use of 'args' argument, + * pkgIndex.tcl: reported in [SF Tcllib Bug 1826418], by Erik + * ansi_cctrl.man: Leunissen. Bumped to version 0.1.1. + +2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.10 ======================== + * + +2007-03-22 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * ansi_cattr.man: Fixed all warnings due to use of now + * ansi_cctrl.man: deprecated. Added a section about how + * ansi_cmacros.man: to give feedback. + * ansi_code.man: + * ansi_ctrlu.man: + * ansi_send.man: + * imenu.man: + * ipager.man: + * receive.man: + * term.man: + * term_bind.man: + * term_send.man: + +2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.9 ======================== + * + +2006-08-09 Andreas Kupries <andreask@activestate.com> + + * ../../examples/term/menu2: Updated to changes in the + package term::receive::bind. + * term_bind.man: Updated documentation as well. + +2006-07-24 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * bind.tcl: Added methods 'default' and 'unlisten', changed action + callbacks to take the invoking character sequence. + * term_bind.man: Documented above changes. + + * imenu.tcl: New packages, terminal widgets, menu and paging text + * ipager.tcl: display. + + * imenu.man: Documentation for the new packages above. + * ipager.man: + + * ../../examples/term/imenu: Examples for the new packages. + * ../../examples/term/ipager: + +2006-07-23 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * receive.tcl: New file, package. Basic receiver functionality + * receive.man: (getting chars, event listener). Documentation. + + * bind.tcl: New file, package. Recognition of character + * term_bind.man: sequences in the input, execution of + actions. Dispatcher. A 'bind' for character sequences. + + * pkgIndex.tcl: New packages registered. + + * ../../examples/term/menu2: Example for receive and bind. + + * ansi_code.man: Typos. + * ansi_send.man: + * term.man: + * term_send.man: + + * ansi/ctrlunix.tcl: New file, package. Control operations, unix + * ansi_ctrlu.man: specific, dependent on external commands + (stty, tput). Documentation. + * pkgIndex.tcl: New package registered. + + * ansi_cctrl.man: Fixed typos. + * ansi_cmacros.man: + +2006-07-21 Andreas Kupries <andreask@activestate.com> + + * send.man: Renamed to term_send.man, to avoid + * term_send.man: clashing with Tk's 'send' manpage. + +2006-07-21 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * ansi_cattr.man: More documentation. + * ansi_cctrl.man: + * ansi_cmacros.man: + * ansi_code.man: + * ansi_send.man: Tweaked + * ansi/code/ctrl.tcl: Fixed argument bug + * ansi/code/macros.tcl: Fixed argument bug. + +2006-07-18 Andreas Kupries <andreask@activestate.com> + + * term.man: Added some documentation. + * send.man: + * ansi_send.man: + +2006-07-10 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * New module "term". Terminal control. diff --git a/tcllib/modules/term/ansi/code.tcl b/tcllib/modules/term/ansi/code.tcl new file mode 100644 index 0000000..a8f7d3e --- /dev/null +++ b/tcllib/modules/term/ansi/code.tcl @@ -0,0 +1,56 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - ANSI +## Generic commands to define commands for code sequences. + +# ### ### ### ######### ######### ######### +## Requirements + +namespace eval ::term::ansi::code {} + +# ### ### ### ######### ######### ######### +## API. Escape clauses, plain and bracket +## Used by 'define'd commands. + +proc ::term::ansi::code::esc {str} {return \033$str} +proc ::term::ansi::code::escb {str} {esc \[$str} + +# ### ### ### ######### ######### ######### +## API. Define command for named control code, or constant. +## (Simple definitions without arguments) + +proc ::term::ansi::code::define {name escape code} { + proc [Qualified $name] {} [list ::term::ansi::code::$escape $code] +} + +proc ::term::ansi::code::const {name code} { + proc [Qualified $name] {} [list return $code] +} + +# ### ### ### ######### ######### ######### +## Internal helper to construct fully-qualified names. + +proc ::term::ansi::code::Qualified {name} { + if {![string match ::* $name]} { + # Get the caller's namespace; append :: if it is not the + # global namespace, for separation from the actual name. + set ns [uplevel 2 [list namespace current]] + if {$ns ne "::"} {append ns ::} + set name $ns$name + } + return $name +} + +# ### ### ### ######### ######### ######### + +namespace eval ::term::ansi::code { + namespace export esc escb define const +} + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::ansi::code 0.2 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ansi/code/attr.tcl b/tcllib/modules/term/ansi/code/attr.tcl new file mode 100644 index 0000000..842beda --- /dev/null +++ b/tcllib/modules/term/ansi/code/attr.tcl @@ -0,0 +1,108 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - ANSI - Attribute codes + +# ### ### ### ######### ######### ######### +## Requirements + +package require term::ansi::code ; # Constants + +namespace eval ::term::ansi::code::attr {} + +# ### ### ### ######### ######### ######### +## API. Symbolic names. + +proc ::term::ansi::code::attr::names {} { + variable attr + return $attr +} + +proc ::term::ansi::code::attr::import {{ns attr} args} { + if {![llength $args]} {set args *} + set args ::term::ansi::code::attr::[join $args " ::term::ansi::code::attr::"] + uplevel 1 [list namespace eval ${ns} [linsert $args 0 namespace import]] + return +} + +# ### ### ### ######### ######### ######### +## Internal - Setup + +proc ::term::ansi::code::attr::DEF {name value} { + variable attr + const $name $value + lappend attr $name + namespace export $name + return +} + +proc ::term::ansi::code::attr::INIT {} { + # ### ### ### ######### ######### ######### + ## + + # Colors. Foreground <=> Text + DEF fgblack 30 ; # Black + DEF fgred 31 ; # Red + DEF fggreen 32 ; # Green + DEF fgyellow 33 ; # Yellow + DEF fgblue 34 ; # Blue + DEF fgmagenta 35 ; # Magenta + DEF fgcyan 36 ; # Cyan + DEF fgwhite 37 ; # White + DEF fgdefault 39 ; # Default (Black) + + # Colors. Background. + DEF bgblack 40 ; # Black + DEF bgred 41 ; # Red + DEF bggreen 42 ; # Green + DEF bgyellow 43 ; # Yellow + DEF bgblue 44 ; # Blue + DEF bgmagenta 45 ; # Magenta + DEF bgcyan 46 ; # Cyan + DEF bgwhite 47 ; # White + DEF bgdefault 49 ; # Default (Transparent) + + # Non-color attributes. Activation. + DEF bold 1 ; # Bold + DEF dim 2 ; # Dim + DEF italic 3 ; # Italics + DEF underline 4 ; # Underscore + DEF blink 5 ; # Blink + DEF revers 7 ; # Reverse + DEF hidden 8 ; # Hidden + DEF strike 9 ; # StrikeThrough + + # Non-color attributes. Deactivation. + DEF nobold 22 ; # Bold + DEF nodim __ ; # Dim + DEF noitalic 23 ; # Italics + DEF nounderline 24 ; # Underscore + DEF noblink 25 ; # Blink + DEF norevers 27 ; # Reverse + DEF nohidden 28 ; # Hidden + DEF nostrike 29 ; # StrikeThrough + + # Remainder + DEF reset 0 ; # Reset + + ## + # ### ### ### ######### ######### ######### + return +} + +# ### ### ### ######### ######### ######### +## Data structures. + +namespace eval ::term::ansi::code::attr { + namespace import ::term::ansi::code::const + variable attr {} +} + +::term::ansi::code::attr::INIT + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::ansi::code::attr 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ansi/code/ctrl.tcl b/tcllib/modules/term/ansi/code/ctrl.tcl new file mode 100644 index 0000000..167ae80 --- /dev/null +++ b/tcllib/modules/term/ansi/code/ctrl.tcl @@ -0,0 +1,270 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - ANSI - Control codes + +## References +# [0] Google: ansi terminal control +# [1] http://vt100.net/docs/vt100-ug/chapter3.html +# [2] http://www.termsys.demon.co.uk/vtansi.htm +# [3] http://rrbrandt.dyndns.org:60000/docs/tut/redes/ansi.php +# [4] http://www.dee.ufcg.edu.br/~rrbrandt/tools/ansi.html +# [5] http://www.ecma-international.org/publications/standards/Ecma-048.htm + +# ### ### ### ######### ######### ######### +## Requirements + +package require term::ansi::code +package require term::ansi::code::attr + +namespace eval ::term::ansi::code::ctrl {} + +# ### ### ### ######### ######### ######### +## API. Symbolic names. + +proc ::term::ansi::code::ctrl::names {} { + variable ctrl + return $ctrl +} + +proc ::term::ansi::code::ctrl::import {{ns ctrl} args} { + if {![llength $args]} {set args *} + set args ::term::ansi::code::ctrl::[join $args " ::term::ansi::code::ctrl::"] + uplevel 1 [list namespace eval $ns [linsert $args 0 namespace import]] + return +} + +# ### ### ### ######### ######### ######### + +## TODO = symbolic key codes for skd. + +# ### ### ### ######### ######### ######### +## Internal - Setup + +proc ::term::ansi::code::ctrl::DEF {name esc value} { + variable ctrl + define $name $esc $value + lappend ctrl $name + namespace export $name + return +} + +proc ::term::ansi::code::ctrl::DEFC {name arguments script} { + variable ctrl + proc $name $arguments $script + lappend ctrl $name + namespace export $name + return +} + +proc ::term::ansi::code::ctrl::INIT {} { + # ### ### ### ######### ######### ######### + ## + + # Erasing + + DEF eeol escb K ; # Erase (to) End Of Line + DEF esol escb 1K ; # Erase (to) Start Of Line + DEF el escb 2K ; # Erase (current) Line + DEF ed escb J ; # Erase Down (to bottom) + DEF eu escb 1J ; # Erase Up (to top) + DEF es escb 2J ; # Erase Screen + + # Scrolling + + DEF sd esc D ; # Scroll Down + DEF su esc M ; # Scroll Up + + # Cursor Handling + + DEF ch escb H ; # Cursor Home + DEF sc escb s ; # Save Cursor + DEF rc escb u ; # Restore Cursor (Unsave) + DEF sca esc 7 ; # Save Cursor + Attributes + DEF rca esc 8 ; # Restore Cursor + Attributes + + # Tabbing + + DEF st esc H ; # Set Tab (@ current position) + DEF ct escb g ; # Clear Tab (@ current position) + DEF cat escb 3g ; # Clear All Tabs + + # Device Introspection + + DEF qdc escb c ; # Query Device Code + DEF qds escb 5n ; # Query Device Status + DEF qcp escb 6n ; # Query Cursor Position + DEF rd esc c ; # Reset Device + + # Linewrap on/off + + DEF elw escb 7h ; # Enable Line Wrap + DEF dlw escb 7l ; # Disable Line Wrap + + # Graphics Mode (aka use alternate font on/off) + + DEF eg esc F ; # Enter Graphics Mode + DEF lg esc G ; # Exit Graphics Mode + + ## + # ### ### ### ######### ######### ######### + + # ### ### ### ######### ######### ######### + ## Complex, parameterized codes + + # Select Character Set + # Choose which char set is used for default and + # alternate font. This does not change whether + # default or alternate font are used + + DEFC scs0 {tag} {esc ($tag} ; # Set default character set + DEFC scs1 {tag} {esc )$tag} ; # Set alternate character set + + # tags in A : United Kingdom Set + # B : ASCII Set + # 0 : Special Graphics + # 1 : Alternate Character ROM Standard Character Set + # 2 : Alternate Character ROM Special Graphics + + # Set Display Attributes + + DEFC sda {args} {escb [join $args \;]m} + + # Force Cursor Position (aka Go To) + + DEFC fcp {r c} {escb ${r}\;${c}f} + + # Cursor Up, Down, Forward, Backward + + DEFC cu {{n 1}} {escb [expr {$n == 1 ? "A" : "${n}A"}]} + DEFC cd {{n 1}} {escb [expr {$n == 1 ? "B" : "${n}B"}]} + DEFC cf {{n 1}} {escb [expr {$n == 1 ? "C" : "${n}C"}]} + DEFC cb {{n 1}} {escb [expr {$n == 1 ? "D" : "${n}D"}]} + + # Scroll Screen (entire display, or between rows start end, inclusive). + + DEFC ss {args} { + if {[llength $args] == 0} {return [escb r]} + if {[llength $args] == 2} {foreach {s e} $args break ; return [escb ${s};${e}r]} + return -code error "wrong\#args" + } + + # Set Key Definition + + DEFC skd {code str} {escb $code\;\"$str\"p} + + # Terminal title + + DEFC title {str} {esc \]0\;$str\007} + + # Switch to and from character/box graphics. + + DEFC gron {} {return \016} + DEFC groff {} {return \017} + + # Character graphics, box symbols + # - 4 corners, 4 t-junctions, + # one 4-way junction, 2 lines + + DEFC tlc {} {return [gron]l[groff]} ; # Top Left Corner + DEFC trc {} {return [gron]k[groff]} ; # Top Right Corner + DEFC brc {} {return [gron]j[groff]} ; # Bottom Right Corner + DEFC blc {} {return [gron]m[groff]} ; # Bottom Left Corner + + DEFC ltj {} {return [gron]t[groff]} ; # Left T Junction + DEFC ttj {} {return [gron]w[groff]} ; # Top T Junction + DEFC rtj {} {return [gron]u[groff]} ; # Right T Junction + DEFC btj {} {return [gron]v[groff]} ; # Bottom T Junction + + DEFC fwj {} {return [gron]n[groff]} ; # Four-Way Junction + + DEFC hl {} {return [gron]q[groff]} ; # Horizontal Line + DEFC vl {} {return [gron]x[groff]} ; # Vertical Line + + # Optimize character graphics. The generator commands above create + # way to many superfluous commands shifting into and out of the + # graphics mode. The command below removes all shifts which are + # not needed. To this end it also knows which characters will look + # the same in both modes, to handle strings created outside this + # package. + + DEFC groptim {string} { + variable grforw + variable grback + while {![string equal $string [set new [string map \ + [list \017\016 {} \016\017 {}] [string map \ + $grback [string map \ + $grforw $string]]]]]} { + set string $new + } + return $string + } + + ## + # ### ### ### ######### ######### ######### + + # ### ### ### ######### ######### ######### + ## Higher level operations + + # Clear screen <=> CursorHome + EraseDown + # Init (Fonts): Default ASCII, Alternate Graphics + # Show a block of text at a specific location. + + DEFC clear {} {return [ch][ed]} + DEFC init {} {return [scs0 B][scs1 0]} + + DEFC showat {r c text} { + if {![string length $text]} {return {}} + return [fcp $r $c][sca][join \ + [split $text \n] \ + [rca][cd][sca]][rca][cd] + } + + ## + # ### ### ### ######### ######### ######### + + # ### ### ### ######### ######### ######### + ## Attribute control (single attributes) + + foreach a [::term::ansi::code::attr::names] { + DEF sda_$a escb [::term::ansi::code::attr::$a]m + } + + ## + # ### ### ### ######### ######### ######### + return +} + +# ### ### ### ######### ######### ######### +## Data structures. + +namespace eval ::term::ansi::code::ctrl { + namespace import ::term::ansi::code::define + namespace import ::term::ansi::code::esc + namespace import ::term::ansi::code::escb + + variable grforw + variable grback + variable _ + + foreach _ { + ! \" # $ % & ' ( ) * + , - . / + 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 [ ^ + \\ ] + } { + lappend grforw \016$_ $_\016 + lappend grback $_\017 \017$_ + } + unset _ +} + +::term::ansi::code::ctrl::INIT + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::ansi::code::ctrl 0.2 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ansi/code/macros.tcl b/tcllib/modules/term/ansi/code/macros.tcl new file mode 100644 index 0000000..1f1d47d --- /dev/null +++ b/tcllib/modules/term/ansi/code/macros.tcl @@ -0,0 +1,93 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - ANSI - Higher level macros + +# ### ### ### ######### ######### ######### +## Requirements + +package require textutil::repeat +package require textutil::tabify +package require term::ansi::code::ctrl + +namespace eval ::term::ansi::code::macros {} + +# ### ### ### ######### ######### ######### +## API. Symbolic names. + +proc ::term::ansi::code::macros::import {{ns macros} args} { + if {![llength $args]} {set args *} + set args ::term::ansi::code::macros::[join $args " ::term::ansi::code::macros::"] + uplevel 1 [list namespace eval ${ns} [linsert $args 0 namespace import]] + return +} + +# ### ### ### ######### ######### ######### +## Higher level operations + +# Format a menu / framed block of text + +proc ::term::ansi::code::macros::menu {menu} { + # Menu = dict (label => char) + array set _ {} + set shift 0 + foreach {label c} $menu { + if {[string first $c $label] < 0} { + set shift 1 + break + } + } + set max 0 + foreach {label c} $menu { + set pos [string first $c $label] + if {$shift || ($pos < 0)} { + set xlabel "$c $label" + set pos 0 + } else { + set xlabel $label + } + set len [string length $xlabel] + if {$len > $max} {set max $len} + set _($label) " [string replace $xlabel $pos $pos \ + [cd::sda_fgred][cd::sda_bold][string index $xlabel $pos][cd::sda_reset]]" + } + + append ms [cd::tlc][textutil::repeat::strRepeat [cd::hl] $max][cd::trc]\n + foreach {l c} $menu {append ms $_($l)\n} + append ms [cd::blc][textutil::repeat::strRepeat [cd::hl] $max][cd::brc] + + return [cd::groptim $ms] +} + +proc ::term::ansi::code::macros::frame {string} { + set lines [split [textutil::tabify::untabify2 $string] \n] + set max 0 + foreach l $lines { + if {[set len [string length $l]] > $max} {set max $len} + } + append fs [cd::tlc][textutil::repeat::strRepeat [cd::hl] $max][cd::trc]\n + foreach l $lines { + append fs [cd::vl]${l}[textutil::repeat::strRepeat " " [expr {$max-[string length $l]}]][cd::vl]\n + } + append fs [cd::blc][textutil::repeat::strRepeat [cd::hl] $max][cd::brc] + return [cd::groptim $fs] +} + +## +# ### ### ### ######### ######### ######### + +# ### ### ### ######### ######### ######### +## Data structures. + +namespace eval ::term::ansi::code::macros { + term::ansi::code::ctrl::import cd + + namespace export menu frame +} + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::ansi::code::macros 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ansi/ctrlunix.tcl b/tcllib/modules/term/ansi/ctrlunix.tcl new file mode 100644 index 0000000..675348c --- /dev/null +++ b/tcllib/modules/term/ansi/ctrlunix.tcl @@ -0,0 +1,91 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - ANSI - Control operations +## (Unix specific implementation). + +## This was originally taken from page 11820 (Pure Tcl Console Editor) +## of the Tcler's Wiki, however page 14693 (Reading a single character +## ...) is the same in a more self-contained manner. + +# ### ### ### ######### ######### ######### +## Requirements + +namespace eval ::term::ansi::ctrl::unix {} + +# ### ### ### ######### ######### ######### +## Make command easily available + +proc ::term::ansi::ctrl::unix::import {{ns ctrl} args} { + if {![llength $args]} {set args *} + set args ::term::ansi::ctrl::unix::[join $args " ::term::ansi::ctrl::unix::"] + uplevel 1 [list namespace eval ${ns} [linsert $args 0 namespace import]] + return +} + +# ### ### ### ######### ######### ######### +## API + +# We use the <@stdin because stty works out what terminal to work with +# using standard input on some platforms. On others it prefers +# /dev/tty instead, but putting in the redirection makes the code more +# portable + +proc ::term::ansi::ctrl::unix::raw {} { + variable stty + exec $stty raw -echo <@stdin + return +} + +proc ::term::ansi::ctrl::unix::cooked {} { + variable stty + exec $stty -raw echo <@stdin + return +} + +proc ::term::ansi::ctrl::unix::columns {} { + variable tput + return [exec $tput cols <@stdin] +} + +proc ::term::ansi::ctrl::unix::rows {} { + variable tput + return [exec $tput lines <@stdin] +} + +# ### ### ### ######### ######### ######### +## Package setup + +proc ::term::ansi::ctrl::unix::INIT {} { + variable tput [auto_execok tput] + variable stty [auto_execok stty] + + if {($stty eq "/usr/ucb/stty") && + ($::tcl_platform(os) eq "SunOS")} { + set stty /usr/bin/stty + } + + if {($tput eq "") || ($stty eq "")} { + return -code error \ + "The external requirements for the \ + use of this package (tput, stty in \ + \$PATH) are not met." + } + return +} + +namespace eval ::term::ansi::ctrl::unix { + variable tput {} + variable stty {} + + namespace export columns rows raw cooked +} + +::term::ansi::ctrl::unix::INIT + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::ansi::ctrl::unix 0.1.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ansi/send.tcl b/tcllib/modules/term/ansi/send.tcl new file mode 100644 index 0000000..d47f834 --- /dev/null +++ b/tcllib/modules/term/ansi/send.tcl @@ -0,0 +1,92 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - ANSI - Control codes + +# ### ### ### ######### ######### ######### +## Requirements + +package require Tcl 8.4 +package require term::send +package require term::ansi::code::ctrl + +namespace eval ::term::ansi::send {} + +# ### ### ### ######### ######### ######### +## Make command easily available + +proc ::term::ansi::send::import {{ns send} args} { + if {![llength $args]} {set args *} + set args ::term::ansi::send::[join $args " ::term::ansi::send::"] + uplevel 1 [list namespace eval ${ns} [linsert $args 0 namespace import]] + return +} + +# ### ### ### ######### ######### ######### +## Internal - Setup. + +proc ::term::ansi::send::ChName {n} { + if {![string match *-* $n]} { + return ${n}ch + } + set nl [split $n -] + set stem [lindex $nl 0] + set sfx [join [lrange $nl 1 end] -] + return ${stem}ch-$sfx +} + +proc ::term::ansi::send::Args {n -> arv achv avv} { + upvar 1 $arv a $achv ach $avv av + set code ::term::ansi::code::ctrl::$n + set a [info args $code] + set av [expr { + [llength $a] + ? " \$[join $a { $}]" + : $a + }] + foreach a1 $a[set a {}] { + if {[info default $code $a1 default]} { + lappend a [list $a1 $default] + } else { + lappend a $a1 + } + } + set ach [linsert $a 0 ch] + return $code +} + +proc ::term::ansi::send::INIT {} { + foreach n [::term::ansi::code::ctrl::names] { + set nch [ChName $n] + set code [Args $n -> a ach av] + + if {[lindex $a end] eq "args"} { + # An args argument requires more care, and an eval + set av [lrange $av 0 end-1] + if {$av ne {}} {set av " $av"} + set gen "eval \[linsert \$args 0 $code$av\]" + #8.5: (written for clarity): set gen "$code$av {*}\$args" + } else { + set gen $code$av + } + + proc $n $a "wr \[$gen\]" ; namespace export $n + proc $nch $ach "wrch \$ch \[$gen\]" ; namespace export $nch + } + return +} + +namespace eval ::term::ansi::send { + namespace import ::term::send::wr + namespace import ::term::send::wrch + namespace export wr wrch +} + +::term::ansi::send::INIT + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::ansi::send 0.2 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ansi_cattr.man b/tcllib/modules/term/ansi_cattr.man new file mode 100644 index 0000000..85f39bf --- /dev/null +++ b/tcllib/modules/term/ansi_cattr.man @@ -0,0 +1,83 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::ansi::code::attr n 0.1] +[keywords ansi] +[keywords {attribute control}] +[keywords {color control}] +[keywords control] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {ANSI attribute sequences}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::ansi::code [opt 0.1]] +[require term::ansi::code::attr [opt 0.1]] +[description] + +This package provides symbolic names for the ANSI attribute control +codes. For each control code a single command is provided which +returns this code as its result. None of the commands of this package +write to a channel; that is handled by higher level packages, like +[package term::ansi::send]. + +[section API] +[subsection Introspection] + +[list_begin definitions] +[call [cmd ::term::ansi::code::attr::names]] + +This command is for introspection. It returns as its result a list +containing the names of all attribute commands. + +[call [cmd ::term::ansi::code::attr::import] [opt [arg ns]] [opt [arg arg]...]] + +This command imports some or all attribute commands into the namespace +[arg ns]. This is by default the namespace [emph attr]. Note that this +is relative namespace name, placing the imported command into a child +of the current namespace. By default all commands are imported, this +can howver be restricted by listing the names of the wanted commands +after the namespace argument. + +[list_end] + +[subsection Attributes] +[list_begin definitions] +[call [cmd ::term::ansi::code::attr::fgblack]] Set text color to [emph Black]. +[call [cmd ::term::ansi::code::attr::fgred]] Set text color to [emph Red]. +[call [cmd ::term::ansi::code::attr::fggreen]] Set text color to [emph Green]. +[call [cmd ::term::ansi::code::attr::fgyellow]] Set text color to [emph Yellow]. +[call [cmd ::term::ansi::code::attr::fgblue]] Set text color to [emph Blue]. +[call [cmd ::term::ansi::code::attr::fgmagenta]] Set text color to [emph Magenta]. +[call [cmd ::term::ansi::code::attr::fgcyan]] Set text color to [emph Cyan]. +[call [cmd ::term::ansi::code::attr::fgwhite]] Set text color to [emph White]. +[call [cmd ::term::ansi::code::attr::fgdefault]] Set default text color ([emph Black]). +[call [cmd ::term::ansi::code::attr::bgblack]] Set background to [emph Black]. +[call [cmd ::term::ansi::code::attr::bgred]] Set background to [emph Red]. +[call [cmd ::term::ansi::code::attr::bggreen]] Set background to [emph Green]. +[call [cmd ::term::ansi::code::attr::bgyellow]] Set background to [emph Yellow]. +[call [cmd ::term::ansi::code::attr::bgblue]] Set background to [emph Blue]. +[call [cmd ::term::ansi::code::attr::bgmagenta]] Set background to [emph Magenta]. +[call [cmd ::term::ansi::code::attr::bgcyan]] Set background to [emph Cyan]. +[call [cmd ::term::ansi::code::attr::bgwhite]] Set background to [emph White]. +[call [cmd ::term::ansi::code::attr::bgdefault]] Set default background (Transparent). +[call [cmd ::term::ansi::code::attr::bold]] Bold on. +[call [cmd ::term::ansi::code::attr::dim]] Dim on. +[call [cmd ::term::ansi::code::attr::italic]] Italics on. +[call [cmd ::term::ansi::code::attr::underline]] Underscore on. +[call [cmd ::term::ansi::code::attr::blink]] Blink on. +[call [cmd ::term::ansi::code::attr::revers]] Reverse on. +[call [cmd ::term::ansi::code::attr::hidden]] Hidden on. +[call [cmd ::term::ansi::code::attr::strike]] Strike-through on. +[call [cmd ::term::ansi::code::attr::nobold]] Bold off. +[call [cmd ::term::ansi::code::attr::noitalic]] Italics off. +[call [cmd ::term::ansi::code::attr::nounderline]] Underscore off. +[call [cmd ::term::ansi::code::attr::noblink]] Blink off. +[call [cmd ::term::ansi::code::attr::norevers]] Reverse off. +[call [cmd ::term::ansi::code::attr::nohidden]] Hidden off. +[call [cmd ::term::ansi::code::attr::nostrike]] Strike-through off. +[call [cmd ::term::ansi::code::attr::reset]] Reset all attributes to their default values. +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/ansi_cctrl.man b/tcllib/modules/term/ansi_cctrl.man new file mode 100644 index 0000000..22edc7a --- /dev/null +++ b/tcllib/modules/term/ansi_cctrl.man @@ -0,0 +1,199 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::ansi::code::ctrl n 0.2] +[keywords ansi] +[keywords {attribute control}] +[keywords {color control}] +[keywords control] +[keywords terminal] +[copyright {2006-2008 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {ANSI control sequences}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::ansi::code [opt 0.2]] +[require term::ansi::code::ctrl [opt 0.2]] +[description] + +This package provides symbolic names for the ANSI control +sequences. For each sequence a single command is provided which +returns the sequence as its result. None of the commands of this +package write to a channel; that is handled by higher level packages, +like [package term::ansi::send]. + +[section API] +[subsection Introspection] + +[list_begin definitions] +[call [cmd ::term::ansi::code::ctrl::names]] + +This command is for introspection. It returns as its result a list +containing the names of all attribute commands. + +[call [cmd ::term::ansi::code::ctrl::import] [opt [arg ns]] [opt [arg arg]...]] + +This command imports some or all attribute commands into the namespace +[arg ns]. This is by default the namespace [emph ctrl]. Note that this +is relative namespace name, placing the imported command into a child +of the current namespace. By default all commands are imported, this +can howver be restricted by listing the names of the wanted commands +after the namespace argument. + +[list_end] + +[subsection Sequences] +[list_begin definitions] +[call [cmd ::term::ansi::code::ctrl::eeol]] Erase (to) End Of Line +[call [cmd ::term::ansi::code::ctrl::esol]] Erase (to) Start Of Line +[call [cmd ::term::ansi::code::ctrl::el]] Erase (current) Line +[call [cmd ::term::ansi::code::ctrl::ed]] Erase Down (to bottom) +[call [cmd ::term::ansi::code::ctrl::eu]] Erase Up (to top) +[call [cmd ::term::ansi::code::ctrl::es]] Erase Screen +[call [cmd ::term::ansi::code::ctrl::sd]] Scroll Down +[call [cmd ::term::ansi::code::ctrl::su]] Scroll Up +[call [cmd ::term::ansi::code::ctrl::ch]] Cursor Home +[call [cmd ::term::ansi::code::ctrl::sc]] Save Cursor +[call [cmd ::term::ansi::code::ctrl::rc]] Restore Cursor (Unsave) +[call [cmd ::term::ansi::code::ctrl::sca]] Save Cursor + Attributes +[call [cmd ::term::ansi::code::ctrl::rca]] Restore Cursor + Attributes +[call [cmd ::term::ansi::code::ctrl::st]] Set Tab (@ current position) +[call [cmd ::term::ansi::code::ctrl::ct]] Clear Tab (@ current position) +[call [cmd ::term::ansi::code::ctrl::cat]] Clear All Tabs +[call [cmd ::term::ansi::code::ctrl::qdc]] Query Device Code +[call [cmd ::term::ansi::code::ctrl::qds]] Query Device Status +[call [cmd ::term::ansi::code::ctrl::qcp]] Query Cursor Position +[call [cmd ::term::ansi::code::ctrl::rd]] Reset Device +[call [cmd ::term::ansi::code::ctrl::elw]] Enable Line Wrap +[call [cmd ::term::ansi::code::ctrl::dlw]] Disable Line Wrap +[call [cmd ::term::ansi::code::ctrl::eg]] Enter Graphics Mode +[call [cmd ::term::ansi::code::ctrl::lg]] Exit Graphics Mode + +[call [cmd ::term::ansi::code::ctrl::scs0] [arg tag]] Set default character set +[call [cmd ::term::ansi::code::ctrl::scs1] [arg tag]] Set alternate character set + +Select Character Set. +[para] + +Choose which character set is used for either default (scs0) or +alternate font (scs1). This does not change whether default or +alternate font are used, only their definition. + +[para] +The legal tags, and their meanings, are: + +[list_begin definitions] +[def A] United Kingdom Set +[def B] ASCII Set +[def 0] Special Graphics +[def 1] Alternate Character ROM Standard Character Set +[def 2] Alternate Character ROM Special Graphics +[list_end] + +[call [cmd ::term::ansi::code::ctrl::sda] [arg arg]...] + +Set Display Attributes. The arguments are the code sequences for the possible +attributes, as provided by the package [package term::ansi::code::attr]. For +convenience this package also provides additional commands each setting a single +specific attribute. + +[call [cmd ::term::ansi::code::ctrl::sda_fgblack]] Set text color to [emph Black]. +[call [cmd ::term::ansi::code::ctrl::sda_fgred]] Set text color to [emph Red]. +[call [cmd ::term::ansi::code::ctrl::sda_fggreen]] Set text color to [emph Green]. +[call [cmd ::term::ansi::code::ctrl::sda_fgyellow]] Set text color to [emph Yellow]. +[call [cmd ::term::ansi::code::ctrl::sda_fgblue]] Set text color to [emph Blue]. +[call [cmd ::term::ansi::code::ctrl::sda_fgmagenta]] Set text color to [emph Magenta]. +[call [cmd ::term::ansi::code::ctrl::sda_fgcyan]] Set text color to [emph Cyan]. +[call [cmd ::term::ansi::code::ctrl::sda_fgwhite]] Set text color to [emph White]. +[call [cmd ::term::ansi::code::ctrl::sda_fgdefault]] Set default text color ([emph Black]). +[call [cmd ::term::ansi::code::ctrl::sda_bgblack]] Set background to [emph Black]. +[call [cmd ::term::ansi::code::ctrl::sda_bgred]] Set background to [emph Red]. +[call [cmd ::term::ansi::code::ctrl::sda_bggreen]] Set background to [emph Green]. +[call [cmd ::term::ansi::code::ctrl::sda_bgyellow]] Set background to [emph Yellow]. +[call [cmd ::term::ansi::code::ctrl::sda_bgblue]] Set background to [emph Blue]. +[call [cmd ::term::ansi::code::ctrl::sda_bgmagenta]] Set background to [emph Magenta]. +[call [cmd ::term::ansi::code::ctrl::sda_bgcyan]] Set background to [emph Cyan]. +[call [cmd ::term::ansi::code::ctrl::sda_bgwhite]] Set background to [emph White]. +[call [cmd ::term::ansi::code::ctrl::sda_bgdefault]] Set default background (Transparent). +[call [cmd ::term::ansi::code::ctrl::sda_bold]] Bold on. +[call [cmd ::term::ansi::code::ctrl::sda_dim]] Dim on. +[call [cmd ::term::ansi::code::ctrl::sda_italic]] Italics on. +[call [cmd ::term::ansi::code::ctrl::sda_underline]] Underscore on. +[call [cmd ::term::ansi::code::ctrl::sda_blink]] Blink on. +[call [cmd ::term::ansi::code::ctrl::sda_revers]] Reverse on. +[call [cmd ::term::ansi::code::ctrl::sda_hidden]] Hidden on. +[call [cmd ::term::ansi::code::ctrl::sda_strike]] Strike-through on. +[call [cmd ::term::ansi::code::ctrl::sda_nobold]] Bold off. +[call [cmd ::term::ansi::code::ctrl::sda_noitalic]] Italics off. +[call [cmd ::term::ansi::code::ctrl::sda_nounderline]] Underscore off. +[call [cmd ::term::ansi::code::ctrl::sda_noblink]] Blink off. +[call [cmd ::term::ansi::code::ctrl::sda_norevers]] Reverse off. +[call [cmd ::term::ansi::code::ctrl::sda_nohidden]] Hidden off. +[call [cmd ::term::ansi::code::ctrl::sda_nostrike]] Strike-through off. +[call [cmd ::term::ansi::code::ctrl::sda_reset]] Reset all attributes to their default values. + +[call [cmd ::term::ansi::send::fcp] [arg row] [arg col]] + +Force Cursor Position (aka Go To). + +[call [cmd ::term::ansi::code::ctrl::cu] [opt [arg n]]] Cursor Up. [arg n] defaults to 1. +[call [cmd ::term::ansi::code::ctrl::cd] [opt [arg n]]] Cursor Down. [arg n] defaults to 1. +[call [cmd ::term::ansi::code::ctrl::cf] [opt [arg n]]] Cursor Forward. [arg n] defaults to 1. +[call [cmd ::term::ansi::code::ctrl::cb] [opt [arg n]]] Cursor Backward. [arg n] defaults to 1. + +[call [cmd ::term::ansi::code::ctrl::ss] [opt "[arg s] [arg e]"]] + +Scroll Screen (entire display, or between rows start end, inclusive). + +[call [cmd ::term::ansi::code::ctrl::skd] [arg code] [arg str]] + +Set Key Definition. +[comment {-- list the possible codes --}] + +[call [cmd ::term::ansi::code::ctrl::title] [arg str]] + +Set the terminal title. + +[call [cmd ::term::ansi::code::ctrl::gron]] + +Switch to character/box graphics. I.e. switch to the alternate font. + +[call [cmd ::term::ansi::code::ctrl::groff]] + +Switch to regular characters. I.e. switch to the default font. + +[call [cmd ::term::ansi::code::ctrl::tlc]] Character graphics, Top Left Corner. +[call [cmd ::term::ansi::code::ctrl::trc]] Character graphics, Top Right Corner. +[call [cmd ::term::ansi::code::ctrl::brc]] Character graphics, Bottom Right Corner. +[call [cmd ::term::ansi::code::ctrl::blc]] Character graphics, Bottom Left Corner. +[call [cmd ::term::ansi::code::ctrl::ltj]] Character graphics, Left T Junction. +[call [cmd ::term::ansi::code::ctrl::ttj]] Character graphics, Top T Junction. +[call [cmd ::term::ansi::code::ctrl::rtj]] Character graphics, Right T Junction. +[call [cmd ::term::ansi::code::ctrl::btj]] Character graphics, Bottom T Junction. +[call [cmd ::term::ansi::code::ctrl::fwj]] Character graphics, Four-Way Junction. +[call [cmd ::term::ansi::code::ctrl::hl]] Character graphics, Horizontal Line. +[call [cmd ::term::ansi::code::ctrl::vl]] Character graphics, Vertical Line. + +[call [cmd ::term::ansi::code::ctrl::groptim] [arg str]] + +Optimize character graphics. The generator commands above create way to many +superfluous commands shifting into and out of the graphics mode. This command +removes all shifts which are not needed. To this end it also knows which +characters will look the same in both modes, to handle strings created outside +of this package. + +[call [cmd ::term::ansi::code::ctrl::clear]] + +Clear screen. In essence a sequence of CursorHome + EraseDown. + +[call [cmd ::term::ansi::code::ctrl::init]] + +Initialize default and alternate fonts to ASCII and box graphics. + +[call [cmd ::term::ansi::code::ctrl::showat] [arg row] [arg col] [arg text]] + +Format the block of text for display at the specified location. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/ansi_cmacros.man b/tcllib/modules/term/ansi_cmacros.man new file mode 100644 index 0000000..3545adb --- /dev/null +++ b/tcllib/modules/term/ansi_cmacros.man @@ -0,0 +1,66 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::ansi::code::macros n 0.1] +[keywords ansi] +[keywords control] +[keywords frame] +[keywords menu] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Macro sequences}] +[category {Terminal control}] +[require Tcl 8.4] +[require textutil::repeat] +[require textutil::tabify] +[require term::ansi::code::macros [opt 0.1]] +[description] + +This package provides higher level control sequences for more complex +shapes. + +[section API] +[subsection Introspection] + +[list_begin definitions] +[call [cmd ::term::ansi::code::macros::names]] + +This command is for introspection. It returns as its result a list +containing the names of all attribute commands. + +[call [cmd ::term::ansi::code::macros::import] [opt [arg ns]] [opt [arg arg]...]] + +This command imports some or all attribute commands into the namespace +[arg ns]. This is by default the namespace [emph macros]. Note that +this is relative namespace name, placing the imported command into a +child of the current namespace. By default all commands are imported, +this can howver be restricted by listing the names of the wanted +commands after the namespace argument. + +[list_end] + +[subsection Sequences] +[list_begin definitions] + +[call [cmd ::term::ansi::code::macros::menu] [arg menu]] + +The description of a menu is converted into a formatted rectangular +block of text, with the menu command characters highlighted using bold +red text. The result is returned as the result of the command. + +[para] + +The description, [arg menu], is a dictionary mapping from menu label +to command character. + +[call [cmd ::term::ansi::code::macros::frame] [arg string]] + +The paragraph of text contained in the string is padded with spaces at +the right margin, after normalizing internal tabs, and then put into a +frame made of box-graphics. The result is returned as the result of +the command. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/ansi_code.man b/tcllib/modules/term/ansi_code.man new file mode 100644 index 0000000..7baa8c5 --- /dev/null +++ b/tcllib/modules/term/ansi_code.man @@ -0,0 +1,46 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::ansi::code n 0.2] +[keywords control] +[keywords declare] +[keywords define] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Helper for control sequences}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::ansi::code [opt 0.2]] +[description] + +This package provides commands enabling the definition of control +sequences in an easy manner. + +[para] + +[list_begin definitions] +[call [cmd ::term::ansi::code::esc] [arg str]] + +This command returns the argument string, prefixed with the ANSI +escape character, "\033." + +[call [cmd ::term::ansi::code::escb] [arg str]] + +This command returns the argument string, prefixed with a common ANSI +escape sequence, "\033[lb]". + +[call [cmd ::term::ansi::code::define] [arg name] [arg escape] [arg code]] + +This command defines a procedure [arg name] which returns the control +sequence [arg code], beginning with the specified escape sequence, +either [const esc], or [const escb]. + +[call [cmd ::term::ansi::code::const] [arg name] [arg code]] + +This command defines a procedure [arg name] which returns the control +sequence [arg code]. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/ansi_ctrlu.man b/tcllib/modules/term/ansi_ctrlu.man new file mode 100644 index 0000000..1d4e647 --- /dev/null +++ b/tcllib/modules/term/ansi_ctrlu.man @@ -0,0 +1,79 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::ansi::ctrl::unix n 0.1.1] +[keywords ansi] +[keywords columns] +[keywords control] +[keywords cooked] +[keywords {input mode}] +[keywords lines] +[keywords raw] +[keywords rows] +[keywords terminal] +[copyright {2006-2011 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Control operations and queries}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::ansi::ctrl::unix [opt 0.1.1]] +[description] + +[emph {WARNING}]: This package is unix-specific and depends on the +availability of two unix system commands for terminal control, +i.e. [syscmd stty] and [syscmd tput], both of which have to be found +in the [var {$PATH}]. If any of these two commands is missing the +loading of the package will fail. + +[para] + +The package provides commands to switch the standard input of the +current process between [term raw] and [term cooked] input modes, and +to query the size of terminals, i.e. the available number of columns +and lines. + +[section API] +[subsection Introspection] + +[list_begin definitions] +[call [cmd ::term::ansi::ctrl::unix::import] [opt [arg ns]] [opt [arg arg]...]] + +This command imports some or all attribute commands into the namespace +[arg ns]. This is by default the namespace [emph ctrl]. Note that this +is relative namespace name, placing the imported command into a child +of the current namespace. By default all commands are imported, this +can howver be restricted by listing the names of the wanted commands +after the namespace argument. + +[list_end] + +[subsection Operations] +[list_begin definitions] + +[call [cmd ::term::ansi::ctrl::unix::raw]] + +This command switches the standard input of the current process to +[term raw] input mode. This means that from then on all characters +typed by the user are immediately reported to the application instead +of waiting in the OS buffer until the Enter/Return key is received. + +[call [cmd ::term::ansi::ctrl::unix::cooked]] + +This command switches the standard input of the current process to +[term cooked] input mode. This means that from then on all characters +typed by the user are kept in OS buffers for editing until the +Enter/Return key is received. + +[call [cmd ::term::ansi::ctrl::unix::columns]] + +This command queries the terminal connected to the standard input for +the number of columns available for display. + +[call [cmd ::term::ansi::ctrl::unix::rows]] + +This command queries the terminal connected to the standard input for +the number of rows (aka lines) available for display. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/ansi_send.man b/tcllib/modules/term/ansi_send.man new file mode 100644 index 0000000..2a36a29 --- /dev/null +++ b/tcllib/modules/term/ansi_send.man @@ -0,0 +1,266 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::ansi::send n 0.2] +[keywords {character output}] +[keywords control] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Output of ANSI control sequences to terminals}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::ansi::send [opt 0.2]] +[description] + +This package provides commands to send ANSI terminal control sequences to a +terminal. All commands come in two variants, one for sending to any channel, +the other for sending to [emph stdout]. + +[para] + +The commands are defined using the control sequences provided by the package +[package term::ansi::code::ctrl]. They have the same arguments as the commands +they are based on, with the exception of the variant for sending to any channel. +Their first argument is always a channel handle, then followed by the original +arguments. Below we will list only the variant sending to [emph stdout]. + +[list_begin definitions] +[call [cmd ::term::ansi::send::import] [opt [arg ns]] [arg ...]] + +Imports the commands of this package into the namespace [arg ns]. If not specified +it defaults to [emph send]. Note that this default is a relative namespace name, +i.e. the actual namespace will be created under the current namespace. + +[para] + +By default all commands will be imported, this can however be restricted to specific +commands, by listing them after the namespace to import them into. + +[call [cmd ::term::ansi::send::eeol]] + +Erase (to) End Of Line. + +[call [cmd ::term::ansi::send::esol]] + +Erase (to) Start Of Line. + +[call [cmd ::term::ansi::send::el]] + +Erase (current) Line. + +[call [cmd ::term::ansi::send::ed]] + +Erase Down (to bottom). + +[call [cmd ::term::ansi::send::eu]] + +Erase Up (to top). + +[call [cmd ::term::ansi::send::es]] + +Erase Screen. + +[call [cmd ::term::ansi::send::sd]] + +Scroll Down. + +[call [cmd ::term::ansi::send::su]] + +Scroll Up. + +[call [cmd ::term::ansi::send::ch]] + +Cursor Home. + +[call [cmd ::term::ansi::send::sc]] + +Save Cursor. Note: Only one saved position can be handled. +This is no unlimited stack. Saving before restoring will +overwrite the saved data. + +[call [cmd ::term::ansi::send::rc]] + +Restore Cursor (Unsave). + +[call [cmd ::term::ansi::send::sca]] + +Save Cursor + Attributes. + +[call [cmd ::term::ansi::send::rca]] + +Restore Cursor + Attributes. + +[call [cmd ::term::ansi::send::st]] + +Set Tab (@ current position). + +[call [cmd ::term::ansi::send::ct]] + +Clear Tab (@ current position). + +[call [cmd ::term::ansi::send::cat]] + +Clear All Tabs. + +[call [cmd ::term::ansi::send::qdc]] + +Query Device Code. + +[call [cmd ::term::ansi::send::qds]] + +Query Device Status. + +[call [cmd ::term::ansi::send::qcp]] + +Query Cursor Position. + +[call [cmd ::term::ansi::send::rd]] + +Reset Device. + +[call [cmd ::term::ansi::send::elw]] + +Enable Line Wrap. + +[call [cmd ::term::ansi::send::dlw]] + +Disable Line Wrap. + +[call [cmd ::term::ansi::send::eg]] + +Enter Graphics Mode. + +[call [cmd ::term::ansi::send::lg]] + +Exit Graphics Mode. + +[call [cmd ::term::ansi::send::scs0] [arg tag]] +[call [cmd ::term::ansi::send::scs1] [arg tag]] + +Select Character Set. +[para] + +Choose which character set is used for default (scs0) and alternate font (scs1). +This does not change whether default or alternate font are used, just their +definitions. + +[para] + +The legal tags, and their meanings, are: + +[list_begin definitions] +[def A] United Kingdom Set +[def B] ASCII Set +[def 0] Special Graphics +[def 1] Alternate Character ROM Standard Character Set +[def 2] Alternate Character ROM Special Graphics +[list_end] + +[call [cmd ::term::ansi::send::sda] [arg arg]...] + +Set Display Attributes. The arguments are the code sequences for the possible +attributes, as provided by the package [package term::ansi::code::attr]. For +convenience this package also provides additional commands each setting a single +specific attribute. + +[call [cmd ::term::ansi::send::sda_fgblack]] Set text color to [emph Black]. +[call [cmd ::term::ansi::send::sda_fgred]] Set text color to [emph Red]. +[call [cmd ::term::ansi::send::sda_fggreen]] Set text color to [emph Green]. +[call [cmd ::term::ansi::send::sda_fgyellow]] Set text color to [emph Yellow]. +[call [cmd ::term::ansi::send::sda_fgblue]] Set text color to [emph Blue]. +[call [cmd ::term::ansi::send::sda_fgmagenta]] Set text color to [emph Magenta]. +[call [cmd ::term::ansi::send::sda_fgcyan]] Set text color to [emph Cyan]. +[call [cmd ::term::ansi::send::sda_fgwhite]] Set text color to [emph White]. +[call [cmd ::term::ansi::send::sda_fgdefault]] Set default text color ([emph Black]). +[call [cmd ::term::ansi::send::sda_bgblack]] Set background to [emph Black]. +[call [cmd ::term::ansi::send::sda_bgred]] Set background to [emph Red]. +[call [cmd ::term::ansi::send::sda_bggreen]] Set background to [emph Green]. +[call [cmd ::term::ansi::send::sda_bgyellow]] Set background to [emph Yellow]. +[call [cmd ::term::ansi::send::sda_bgblue]] Set background to [emph Blue]. +[call [cmd ::term::ansi::send::sda_bgmagenta]] Set background to [emph Magenta]. +[call [cmd ::term::ansi::send::sda_bgcyan]] Set background to [emph Cyan]. +[call [cmd ::term::ansi::send::sda_bgwhite]] Set background to [emph White]. +[call [cmd ::term::ansi::send::sda_bgdefault]] Set default background (Transparent). +[call [cmd ::term::ansi::send::sda_bold]] Bold on. +[call [cmd ::term::ansi::send::sda_dim]] Dim on. +[call [cmd ::term::ansi::send::sda_italic]] Italics on. +[call [cmd ::term::ansi::send::sda_underline]] Underscore on. +[call [cmd ::term::ansi::send::sda_blink]] Blink on. +[call [cmd ::term::ansi::send::sda_revers]] Reverse on. +[call [cmd ::term::ansi::send::sda_hidden]] Hidden on. +[call [cmd ::term::ansi::send::sda_strike]] Strike-through on. +[call [cmd ::term::ansi::send::sda_nobold]] Bold off. +[call [cmd ::term::ansi::send::sda_noitalic]] Italics off. +[call [cmd ::term::ansi::send::sda_nounderline]] Underscore off. +[call [cmd ::term::ansi::send::sda_noblink]] Blink off. +[call [cmd ::term::ansi::send::sda_norevers]] Reverse off. +[call [cmd ::term::ansi::send::sda_nohidden]] Hidden off. +[call [cmd ::term::ansi::send::sda_nostrike]] Strike-through off. +[call [cmd ::term::ansi::send::sda_reset]] Reset all attributes to their default values. + +[call [cmd ::term::ansi::send::fcp] [arg row] [arg col]] + +Force Cursor Position (aka Go To). + +[call [cmd ::term::ansi::send::cu] [opt [arg n]]] Cursor Up. [arg n] defaults to 1. +[call [cmd ::term::ansi::send::cd] [opt [arg n]]] Cursor Down. [arg n] defaults to 1. +[call [cmd ::term::ansi::send::cf] [opt [arg n]]] Cursor Forward. [arg n] defaults to 1. +[call [cmd ::term::ansi::send::cb] [opt [arg n]]] Cursor Backward. [arg n] defaults to 1. + +[call [cmd ::term::ansi::send::ss] [opt "[arg s] [arg e]"]] + +Scroll Screen (entire display, or between rows start end, inclusive). + +[call [cmd ::term::ansi::send::skd] [arg code] [arg str]] + +Set Key Definition. +[comment {-- list the possible codes --}] + +[call [cmd ::term::ansi::send::title] [arg str]] + +Set the terminal title. + +[call [cmd ::term::ansi::send::gron]] + +Switch to character/box graphics. I.e. switch to the alternate font. + +[call [cmd ::term::ansi::send::groff]] + +Switch to regular characters. I.e. switch to the default font. + +[call [cmd ::term::ansi::send::tlc]] Character graphics, Top Left Corner. +[call [cmd ::term::ansi::send::trc]] Character graphics, Top Right Corner. +[call [cmd ::term::ansi::send::brc]] Character graphics, Bottom Right Corner. +[call [cmd ::term::ansi::send::blc]] Character graphics, Bottom Left Corner. +[call [cmd ::term::ansi::send::ltj]] Character graphics, Left T Junction. +[call [cmd ::term::ansi::send::ttj]] Character graphics, Top T Junction. +[call [cmd ::term::ansi::send::rtj]] Character graphics, Right T Junction. +[call [cmd ::term::ansi::send::btj]] Character graphics, Bottom T Junction. +[call [cmd ::term::ansi::send::fwj]] Character graphics, Four-Way Junction. +[call [cmd ::term::ansi::send::hl]] Character graphics, Horizontal Line. +[call [cmd ::term::ansi::send::vl]] Character graphics, Vertical Line. + +[call [cmd ::term::ansi::send::groptim] [arg str]] + +Optimize character graphics. The generator commands above create way to many +superfluous commands shifting into and out of the graphics mode. This command +removes all shifts which are not needed. To this end it also knows which +characters will look the same in both modes, to handle strings created outside +of this package. + +[call [cmd ::term::ansi::send::clear]] + +Clear screen. In essence a sequence of CursorHome + EraseDown. + +[call [cmd ::term::ansi::send::init]] + +Initialize default and alternate fonts to ASCII and box graphics. + +[call [cmd ::term::ansi::send::showat] [arg row] [arg col] [arg text]] + +Show the block of text at the specified location. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/bind.tcl b/tcllib/modules/term/bind.tcl new file mode 100644 index 0000000..d269690 --- /dev/null +++ b/tcllib/modules/term/bind.tcl @@ -0,0 +1,132 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - string -> action mappings +## (bind objects). For use with 'receive listen'. +## In essence a DFA with tree structure. + +# ### ### ### ######### ######### ######### +## Requirements + +package require snit +package require term::receive +namespace eval ::term::receive::bind {} + +# ### ### ### ######### ######### ######### + +snit::type ::term::receive::bind { + + constructor {{dict {}}} { + foreach {str cmd} $dict {Register $str $cmd} + return + } + + method map {str cmd} { + Register $str $cmd + return + } + + method default {cmd} { + set default $cmd + return + } + + # ### ### ### ######### ######### ######### + ## + + method listen {{chan stdin}} { + #parray dfa + ::term::receive::listen $self $chan + return + } + + method unlisten {{chan stdin}} { + ::term::receive::unlisten $chan + return + } + + # ### ### ### ######### ######### ######### + ## + + variable default {} + variable state {} + + method reset {} { + set state {} + return + } + + method next {c} {Next $c ; return} + method process {str} { + foreach c [split $str {}] {Next $c} + return + } + + method eof {} {Eof ; return} + + proc Next {c} { + upvar 1 dfa dfa state state default default + set key [list $state $c] + + #puts -nonewline stderr "('$state' x '$c')" + + if {![info exists dfa($key)]} { + # Unknown sequence. Reset. Restart. + # Run it through the default action. + + if {$default ne ""} { + uplevel #0 [linsert $default end $state$c] + } + + #puts stderr =\ RESET + set state {} + } else { + foreach {what detail} $dfa($key) break + #puts -nonewline stderr "= $what '$detail'" + if {$what eq "t"} { + # Incomplete sequence. Next state. + set state $detail + #puts stderr " goto ('$state')" + } elseif {$what eq "a"} { + # Action, then reset. + set state {} + #puts stderr " run ($detail)" + uplevel #0 [linsert $detail end $state$c] + } else { + return -code error \ + "Internal error. Bad DFA." + } + } + return + } + + proc Eof {} {} + + # ### ### ### ######### ######### ######### + ## + + proc Register {str cmd} { + upvar 1 dfa dfa + set prefix {} + set last {{} {}} + foreach c [split $str {}] { + set key [list $prefix $c] + set next $prefix$c + set dfa($key) [list t $next] + set last $key + set prefix $next + } + set dfa($last) [list a $cmd] + } + variable dfa -array {} + + ## + # ### ### ### ######### ######### ######### +} + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::receive::bind 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/imenu.man b/tcllib/modules/term/imenu.man new file mode 100644 index 0000000..122e338 --- /dev/null +++ b/tcllib/modules/term/imenu.man @@ -0,0 +1,155 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::interact::menu n 0.1] +[keywords control] +[keywords menu] +[keywords terminal] +[keywords {text display}] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Terminal widget, menu}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::interact::menu [opt 0.1]] +[description] + +This package provides a class for the creation of a simple menu +control. + +[section {Class API}] + +The package exports a single command, the class command, enabling the +creation of menu instances. Its API is: + +[list_begin definitions] + +[call [cmd term::interact::menu] [arg object] [arg dict] [opt [arg options]...]] + +This command creates a new menu object with the name [arg object], +initializes it, and returns the fully qualified name of the object +command as its result. + +[para] + +The argument is the menu to show, possibly followed by configuration +options and their values. The options are explained in the section +[sectref Configuration]. The menu is a dictionary maping labels +to symbolic action codes. + +[list_end] + +[section {Object API}] + +The objects created by the class command provide the methods listed +below: + +[list_begin definitions] +[call [arg object] [method interact]] + +Shows the menu in the screen at the configured location and starts +interacting with it. This opens its own event loop for the processing +of incoming characters. The method returns when the interaction has +completed. See section [sectref Interaction] for a description of the +possible interaction. + +[para] + +The method returns the symbolic action of the menu item selected by +the user at the end of the interaction. + +[call [arg object] [method done]] + +This method can be used by user supplied actions to terminate the +interaction with the object. + +[call [arg object] [method clear]] + +This method can be used by user supplied actions to remove the menu +from the terminal. + +[call [arg object] [method configure]] +[call [arg object] [method configure] [arg option]] +[call [arg object] [method configure] [arg option] [arg value]...] +[call [arg object] [method cget] [arg option]] + +Standard methods to retrieve and configure the options of the menu. + +[list_end] + +[section Configuration] + +A menu instance recognizes the following options: + +[list_begin options] +[opt_def -in chan] + +Specifies the channel to read character sequences from. Defaults to +[const stdin]. + +[opt_def -out chan] + +Specifies the channel to write the menu contents to. Defaults to +[const stdout]. + +[opt_def -column int] + +Specifies the column of the terminal where the left margin of the +menu display should appear. Defaults to 0, i.e. the left-most +column. + +[opt_def -line int] + +Specifies the line of the terminal where the top margin of the menu +display should appear. Defaults to 0, i.e. the top-most line. + +[opt_def -height int] + +Specifies the number of lines of text to show at most in the +display. Defaults to 25. + +[opt_def -actions dict] + +Specifies a dictionary containing additional actions, using character +sequences as keys. Note that these sequences cannot override the +hardwired sequences described in section [sectref Interaction]. + +[opt_def -hilitleft int] +[opt_def -hilitright int] + +By default the entire selected menu entry is highlighted in revers +output. However, when present these two options restrict revers dispay +to the specified sub-range of the entry. + +[opt_def -framed bool] + +By default the menu is shown using only header and footer out of +characters box graphics. If this flag is set the menu is fully +enclosed in a box. + +[list_end] + +[section Interaction] + +A menu object recognizes the control sequences listed below and acts +as described. The user can supply more control sequences to act on via +the configuration, but is not able to overide these defaults. + +[list_begin definitions] +[def {Cursor Up}] + +The selection is moved up one entry, except if the first entry of the +menu is already selected. + +[def {Cursor Down}] + +The selection is moved down one entry, except if the last entry of the +menu is already selected. + +[def Enter/Return] + +The interaction with the object is terminated. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/imenu.tcl b/tcllib/modules/term/imenu.tcl new file mode 100644 index 0000000..7166b31 --- /dev/null +++ b/tcllib/modules/term/imenu.tcl @@ -0,0 +1,202 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - string -> action mappings +## (menu objects). For use with 'receive listen'. +## In essence a DFA with tree structure. + +# ### ### ### ######### ######### ######### +## Requirements + +package require snit +package require textutil::repeat +package require textutil::tabify +package require term::ansi::send +package require term::receive::bind +package require term::ansi::code::ctrl + +namespace eval ::term::receive::menu {} + +# ### ### ### ######### ######### ######### + +snit::type ::term::interact::menu { + + option -in -default stdin + option -out -default stdout + option -column -default 0 + option -line -default 0 + option -height -default 25 + option -actions -default {} + option -hilitleft -default 0 + option -hilitright -default end + option -framed -default 0 -readonly 1 + + # ### ### ### ######### ######### ######### + ## + + constructor {dict args} { + $self configurelist $args + Save $dict + + install bind using ::term::receive::bind \ + ${selfns}::bind $options(-actions) + + $bind map [cd::cu] [mymethod Up] + $bind map [cd::cd] [mymethod Down] + $bind map \n [mymethod Select] + #$bind default [mymethod DEF] + + return + } + + # ### ### ### ######### ######### ######### + ## + + method interact {} { + Show + $bind listen $options(-in) + vwait [myvar done] + $bind unlisten $options(-in) + return $map($done) + } + + method done {} {set done $at ; return} + method clear {} {Clear ; return} + + # ### ### ### ######### ######### ######### + ## + + component bind + + # ### ### ### ######### ######### ######### + ## + + variable map -array {} + variable header + variable labels + variable footer + variable empty + + proc Save {dict} { + upvar 1 header header labels labels footer footer + upvar 1 empty empty at at map map top top + upvar 1 options(-height) height + + set max 0 + foreach {l code} $dict { + if {[set len [string length $l]] > $max} {set max $len} + } + + set header [cd::groptim [cd::tlc][textutil::repeat::strRepeat [cd::hl] $max][cd::trc]] + set footer [cd::groptim [cd::blc][textutil::repeat::strRepeat [cd::hl] $max][cd::brc]] + + set labels {} + set at 0 + foreach {l code} $dict { + set map($at) $code + lappend labels ${l}[textutil::repeat::strRepeat " " [expr {$max-[string length $l]}]] + incr at + } + + set h $height + if {$h > [llength $labels]} {set h [llength $labels]} + + set eline " [textutil::repeat::strRepeat { } $max]" + set empty $eline + for {set i 0} {$i <= $h} {incr i} { + append empty \n$eline + } + + set at 0 + set top 0 + return + } + + variable top 0 + variable at 0 + variable done . + + proc Show {} { + upvar 1 header header labels labels footer footer at at + upvar 1 options(-in) in options(-column) col top top + upvar 1 options(-out) out options(-line) row + upvar 1 options(-height) height options(-framed) framed + upvar 1 options(-hilitleft) left + upvar 1 options(-hilitright) right + + set bot [expr {$top + $height - 1}] + set fr [expr {$framed ? [cd::vl] : { }}] + + set text $header\n + set i $top + foreach l [lrange $labels $top $bot] { + append text $fr + if {$i != $at} { + append text $l + } else { + append text [string replace $l $left $right \ + [cd::sda_revers][string range $l $left $right][cd::sda_reset]] + } + append text $fr \n + incr i + } + append text $footer + + vt::wrch $out [cd::showat $row $col $text] + return + } + + proc Clear {} { + upvar 1 empty empty options(-column) col + upvar 1 options(-out) out options(-line) row + + vt::wrch $out [cd::showat $row $col $empty] + return + } + + # ### ### ### ######### ######### ######### + ## + + method Up {str} { + if {$at == 0} return + incr at -1 + if {$at < $top} {incr top -1} + Show + return + } + + method Down {str} { + upvar 0 options(-height) height + if {$at == ([llength $labels]-1)} return + incr at + set bot [expr {$top + $height - 1}] + if {$at > $bot} {incr top} + Show + return + } + + method Select {str} { + $self done + return + } + + method DEF {str} { + puts stderr "($str)" + exit + } + + ## + # ### ### ### ######### ######### ######### +} + +# ### ### ### ######### ######### ######### +## Ready + +namespace eval ::term::interact::menu { + term::ansi::code::ctrl::import cd + term::ansi::send::import vt +} + +package provide term::interact::menu 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/ipager.man b/tcllib/modules/term/ipager.man new file mode 100644 index 0000000..b08b50e --- /dev/null +++ b/tcllib/modules/term/ipager.man @@ -0,0 +1,154 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::interact::pager n 0.1] +[keywords control] +[keywords pager] +[keywords terminal] +[keywords {text display}] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Terminal widget, paging}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::interact::pager [opt 0.1]] +[description] + +This package provides a class for the creation of a simple paging +text display. + +[section {Class API}] + +The package exports a single command, the class command, enabling the +creation of pager instances. Its API is: + +[list_begin definitions] + +[call [cmd term::interact::pager] [arg object] [arg text] [opt [arg options]...]] + +This command creates a new pager object with the name [arg object], +initializes it, and returns the fully qualified name of the object +command as its result. + +[para] + +The argument is the text to show, possibly followed by configuration +options and their values. The options are explained in the section +[sectref Configuration]. + +[list_end] + +[section {Object API}] + +The objects created by the class command provide the methods listed +below: + +[list_begin definitions] +[call [arg object] [method interact]] + +Show the pager in the screen at the configured location and start +interacting with it. This opens its own event loop for the processing +of incoming characters. The method returns when the interaction has +completed. See section [sectref Interaction] for a description of the +possible interaction. + +[call [arg object] [method done]] + +This method can be used by user supplied actions to terminate the +interaction with the object. + +[call [arg object] [method clear]] + +This method can be used by user supplied actions to remove the pager +from the terminal. + +[call [arg object] [method text] [arg text]] + +This method can be used to change the text shown by the pager. +The pager will reset the dispay to show the first line of the +text at the top. + +[call [arg object] [method configure]] +[call [arg object] [method configure] [arg option]] +[call [arg object] [method configure] [arg option] [arg value]...] +[call [arg object] [method cget] [arg option]] + +Standard methods to retrieve and configure the options of the pager. + +[list_end] + +[section Configuration] + +A pager instance recognizes the following options: + +[list_begin options] +[opt_def -in chan] + +Specifies the channel to read character sequences from. Defaults to +[const stdin]. + +[opt_def -out chan] + +Specifies the channel to write the pager contents to. Defaults to +[const stdout]. + +[opt_def -column int] + +Specifies the column of the terminal where the left margin of the +pager display should appear. Defaults to 0, i.e. the left-most +column. + +[opt_def -line int] + +Specifies the line of the terminal where the top margin of the pager +display should appear. Defaults to 0, i.e. the top-most line. + +[opt_def -height int] + +Specifies the number of lines of text to show at most in the +display. Defaults to 25. + +[opt_def -actions dict] + +Specifies a dictionary containing additional actions, using character +sequences as keys. Note that these sequences cannot override the +hardwired sequences described in section [sectref Interaction]. + +[list_end] + +[section Interaction] + +A pager object recognizes the control sequences listed below and acts +as described. The user can supply more control sequences to act on via +the configuration, but is not able to overide these defaults. + +[list_begin definitions] +[def {Cursor Up}] + +The text is scrolled down a single line, making one more line visible +at the top. The pager will not react if the first line of the text is +already shown. + +[def {Cursor Down}] + +The text is scrolled up a single line, making one more line visible at +the bottom. The pager will not react if the last line of the text is +already shown. + +[def {Page Up}] + +The text is scrolled down a page. The pager will not react if the +first line of the text is already shown. + +[def {Page Down}] + +The text is scrolled up a page. The pager will not react if the last +line of the text is already shown. + +[def Enter/Return] + +The interaction with the object is terminated. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/ipager.tcl b/tcllib/modules/term/ipager.tcl new file mode 100644 index 0000000..59c1c58 --- /dev/null +++ b/tcllib/modules/term/ipager.tcl @@ -0,0 +1,206 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - string -> action mappings +## (pager objects). For use with 'receive listen'. +## In essence a DFA with tree structure. + +# ### ### ### ######### ######### ######### +## Requirements + +package require snit +package require textutil::repeat +package require textutil::tabify +package require term::ansi::send +package require term::receive::bind +package require term::ansi::code::ctrl + +namespace eval ::term::receive::pager {} + +# ### ### ### ######### ######### ######### + +snit::type ::term::interact::pager { + + option -in -default stdin + option -out -default stdout + option -column -default 0 + option -line -default 0 + option -height -default 25 + option -actions -default {} + + # ### ### ### ######### ######### ######### + ## + + constructor {str args} { + $self configurelist $args + Save $str + + install bind using ::term::receive::bind \ + ${selfns}::bind $options(-actions) + + $bind map [cd::cu] [mymethod Up] + $bind map [cd::cd] [mymethod Down] + $bind map \033\[5~ [mymethod PageUp] + $bind map \033\[6~ [mymethod PageDown] + $bind map \n [mymethod Done] + #$bind default [mymethod DEF] + + return + } + + # ### ### ### ######### ######### ######### + ## + + method interact {} { + Show + $bind listen $options(-in) + set interacting 1 + vwait [myvar done] + set interacting 0 + $bind unlisten $options(-in) + return + } + + method done {} {set done . ; return} + method clear {} {Clear ; return} + + method text {str} { + if {$interacting} {Clear} + Save $str + if {$interacting} {Show} + return + } + + # ### ### ### ######### ######### ######### + ## + + component bind + + # ### ### ### ######### ######### ######### + ## + + variable header + variable text + variable footer + variable empty + + proc Save {str} { + upvar 1 header header text text footer footer maxline maxline + upvar 1 options(-height) height empty empty at at + + set lines [split [textutil::tabify::untabify2 $str] \n] + + set max 0 + foreach l $lines { + if {[set len [string length $l]] > $max} {set max $len} + } + + set header [cd::groptim [cd::tlc][textutil::repeat::strRepeat [cd::hl] $max][cd::trc]] + set footer [cd::groptim [cd::blc][textutil::repeat::strRepeat [cd::hl] $max][cd::brc]] + + set text {} + foreach l $lines { + lappend text [cd::vl]${l}[textutil::repeat::strRepeat " " [expr {$max-[string length $l]}]][cd::vl] + } + + set h $height + if {$h > [llength $text]} {set h [llength $text]} + + set eline " [textutil::repeat::strRepeat { } $max]" + set empty $eline + for {set i 0} {$i <= $h} {incr i} { + append empty \n$eline + } + + set maxline [expr {[llength $text] - $height}] + if {$maxline < 0} {set maxline 0} + set at 0 + return + } + + variable interacting 0 + variable at 0 + variable maxline -1 + variable done . + + proc Show {} { + upvar 1 header header text text footer footer at at + upvar 1 options(-in) in options(-column) col + upvar 1 options(-out) out options(-line) row + upvar 1 options(-height) height + + set to [expr {$at + $height -1}] + + vt::wrch $out [cd::showat $row $col \ + $header\n[join [lrange $text $at $to] \n]\n$footer] + return + } + + proc Clear {} { + upvar 1 empty empty options(-column) col + upvar 1 options(-out) out options(-line) row + + vt::wrch $out [cd::showat $row $col $empty] + return + } + + # ### ### ### ######### ######### ######### + ## + + method Up {str} { + if {$at == 0} return + incr at -1 + Show + return + } + + method Down {str} { + if {$at >= $maxline} return + incr at + Show + return + } + + method PageUp {str} { + set newat [expr {$at - $options(-height) + 1}] + if {$newat < 0} {set newat 0} + if {$newat == $at} return + set at $newat + Show + return + } + + method PageDown {str} { + set newat [expr {$at + $options(-height) - 1}] + if {$newat >= $maxline} {set newat $maxline} + if {$newat == $at} return + set at $newat + Show + return + } + + method Done {str} { + $self done + return + } + + method DEF {str} { + puts stderr "($str)" + exit + } + + ## + # ### ### ### ######### ######### ######### +} + +# ### ### ### ######### ######### ######### +## Ready + +namespace eval ::term::interact::pager { + term::ansi::code::ctrl::import cd + term::ansi::send::import vt +} + +package provide term::interact::pager 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/pkgIndex.tcl b/tcllib/modules/term/pkgIndex.tcl new file mode 100644 index 0000000..ef0e264 --- /dev/null +++ b/tcllib/modules/term/pkgIndex.tcl @@ -0,0 +1,13 @@ +if {![package vsatisfies [package provide Tcl] 8.4]} return +package ifneeded term 0.1 [list source [file join $dir term.tcl]] +package ifneeded term::ansi::code 0.2 [list source [file join $dir ansi/code.tcl]] +package ifneeded term::ansi::code::attr 0.1 [list source [file join $dir ansi/code/attr.tcl]] +package ifneeded term::ansi::code::ctrl 0.2 [list source [file join $dir ansi/code/ctrl.tcl]] +package ifneeded term::ansi::code::macros 0.1 [list source [file join $dir ansi/code/macros.tcl]] +package ifneeded term::ansi::ctrl::unix 0.1.1 [list source [file join $dir ansi/ctrlunix.tcl]] +package ifneeded term::ansi::send 0.2 [list source [file join $dir ansi/send.tcl]] +package ifneeded term::interact::menu 0.1 [list source [file join $dir imenu.tcl]] +package ifneeded term::interact::pager 0.1 [list source [file join $dir ipager.tcl]] +package ifneeded term::receive 0.1 [list source [file join $dir receive.tcl]] +package ifneeded term::receive::bind 0.1 [list source [file join $dir bind.tcl]] +package ifneeded term::send 0.1 [list source [file join $dir send.tcl]] diff --git a/tcllib/modules/term/receive.man b/tcllib/modules/term/receive.man new file mode 100644 index 0000000..fe4713c --- /dev/null +++ b/tcllib/modules/term/receive.man @@ -0,0 +1,77 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::receive n 0.1] +[keywords {character input}] +[keywords control] +[keywords {get character}] +[keywords listener] +[keywords receiver] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {General input from terminals}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::receive [opt 0.1]] +[description] + +This package provides the most primitive commands for receiving +characters to a terminal. They are in essence convenient wrappers +around the builtin commands [cmd read] and [cmd fileevent]. + +[list_begin definitions] +[call [cmd ::term::receive::getch] [opt [arg chan]]] + +This command reads a single character from the channel with handle +[arg chan] and returns it as the result of the command. + +[para] + +If not specified [arg chan] defaults to [const stdin]. + +[para] + +It is the responsibility of the caller to make sure that the channel +can provide single characters. On unix this can be done, for example, +by using the command of package [package term::ansi::ctrl::unix]. + +[call [cmd ::term::receive::listen] [arg cmd] [opt [arg chan]]] + +This command sets up a filevent listener for the channel with handle +[arg chan] and invokes the command prefix [arg cmd] whenever +characters have been received, or EOF was reached. + +[para] + +If not specified [arg chan] defaults to [const stdin]. + +[para] + +The signature of the command prefix is + +[list_begin definitions] +[call [arg cmd] [method process] [arg string]] + +This method is invoked when characters were received, and [arg string] +holds them for processing. + +[call [arg cmd] [method eof]] + +This method is invoked when EOF was reached on the channel we listen +on. It will be the last call to be received by the callback. + +[list_end] + +[call [cmd ::term::receive::unlisten] [opt [arg chan]]] + +This command disables the filevent listener for the channel with handle +[arg chan]. + +[para] + +If not specified [arg chan] defaults to [const stdin]. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/receive.tcl b/tcllib/modules/term/receive.tcl new file mode 100644 index 0000000..393549c --- /dev/null +++ b/tcllib/modules/term/receive.tcl @@ -0,0 +1,60 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - Generic receiver operations + +# ### ### ### ######### ######### ######### +## Requirements + +namespace eval ::term::receive {} + +# ### ### ### ######### ######### ######### +## API. Read character from specific channel, +## or default (stdin). Processing of +## character sequences. + +proc ::term::receive::getch {{chan stdin}} { + return [read $chan 1] +} + +proc ::term::receive::listen {cmd {chan stdin}} { + fconfigure $chan -blocking 0 + fileevent $chan readable \ + [list ::term::receive::Foreach $chan $cmd] + return +} + +proc ::term::receive::unlisten {{chan stdin}} { + fileevent $chan readable {} + return +} + +# ### ### ### ######### ######### ######### +## Internals + +proc ::term::receive::Foreach {chan cmd} { + set string [read $chan] + if {[string length $string]} { + #puts stderr "F($string)" + uplevel #0 [linsert $cmd end process $string] + } + if {[eof $chan]} { + close $chan + uplevel #0 [linsert $cmd end eof] + } + return +} + +# ### ### ### ######### ######### ######### +## Initialization + +namespace eval ::term::receive { + namespace export getch listen +} + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::receive 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/send.tcl b/tcllib/modules/term/send.tcl new file mode 100644 index 0000000..c3e235d --- /dev/null +++ b/tcllib/modules/term/send.tcl @@ -0,0 +1,34 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - Generic sender operations + +# ### ### ### ######### ######### ######### +## Requirements + +namespace eval ::term::send {} + +# ### ### ### ######### ######### ######### +## API. Write to channel, or default (stdout) + +proc ::term::send::wr {str} { + wrch stdout $str + return +} + +proc ::term::send::wrch {ch str} { + puts -nonewline $ch $str + flush $ch + return +} + +namespace eval ::term::send { + namespace export wr wrch +} + +# ### ### ### ######### ######### ######### +## Ready + +package provide term::send 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/term.man b/tcllib/modules/term/term.man new file mode 100644 index 0000000..40d51a3 --- /dev/null +++ b/tcllib/modules/term/term.man @@ -0,0 +1,20 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term n 0.1] +[keywords control] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {General terminal control}] +[category {Terminal control}] +[require Tcl 8.4] +[require term [opt 0.1]] +[description] + +It is planned to have this package provide highlevel general terminal control +commands, in the vein of ncurses or similar packages. Currently nothing has +been implemented however. I.e. this package is empty. It can be loaded, yet +provides nothing. + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/term.tcl b/tcllib/modules/term/term.tcl new file mode 100644 index 0000000..01d4630 --- /dev/null +++ b/tcllib/modules/term/term.tcl @@ -0,0 +1,19 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Terminal packages - Main :: Generic operations + +# Currently we have no generica at all. We make the package, but it +# provides nothing for now. + +# ### ### ### ######### ######### ######### +## Requirements + +namespace eval ::term {} + +# ### ### ### ######### ######### ######### +## Ready + +package provide term 0.1 + +## +# ### ### ### ######### ######### ######### diff --git a/tcllib/modules/term/term_bind.man b/tcllib/modules/term/term_bind.man new file mode 100644 index 0000000..0895a27 --- /dev/null +++ b/tcllib/modules/term/term_bind.man @@ -0,0 +1,124 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::receive::bind n 0.1] +[keywords {character input}] +[keywords control] +[keywords dispatcher] +[keywords listener] +[keywords receiver] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {Keyboard dispatch from terminals}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::receive::bind [opt 0.1]] +[description] + +This package provides a class for the creation of simple dispatchers +from character sequences to actions. Internally each dispatcher is in +essence a deterministic finite automaton with tree structure. + +[section {Class API}] + +The package exports a single command, the +class command, enabling the creation of +dispatcher instances. Its API +is: + +[list_begin definitions] + +[call [cmd term::receive::bind] [arg object] [opt [arg map]]] + +This command creates a new dispatcher object with the name +[arg object], initializes it, and returns the fully qualified name of +the object command as its result. + +[para] + +The argument is a dictionary mapping from strings, i.e. character +sequences to the command prefices to invoke when the sequence is found +in the input stream. + +[list_end] + +[section {Object API}] + +The objects created by the class command provide the methods listed +below: + +[list_begin definitions] +[call [arg object] [method map] [arg str] [arg cmd]] + +This method adds an additional mapping from the string [arg str] to +the action [arg cmd]. The mapping will take effect immediately +should the processor be in a prefix of [arg str], or at the next +reset operation. The action is a command prefix and will be invoked +with one argument appended to it, the character sequence causing +the invokation. It is executed in the global namespace. + +[call [arg object] [method default] [arg cmd]] + +This method defines a default action [arg cmd] which will be invoked +whenever an unknown character sequence is encountered. The command +prefix is handled in the same as the regular action defined via +method [method map]. + +[call [arg object] [method listen] [opt [arg chan]]] + +This methods sets up a filevent listener for the channel with handle +[arg chan] and invokes the dispatcher object whenever characters have +been received, or EOF was reached. + +[para] + +If not specified [arg chan] defaults to [const stdin]. + +[call [arg object] [method unlisten] [opt [arg chan]]] + +This methods removes the filevent listener for the channel with handle +[arg chan]. + +[para] + +If not specified [arg chan] defaults to [const stdin]. + +[call [arg object] [method reset]] + +This method resets the character processor +to the beginning of the tree. + +[call [arg object] [method next] [arg char]] + +This method causes the character processor to process the character +[arg c]. This may simply advance the internal state, or invoke an +associated action for a recognized sequence. + +[call [arg object] [method process] [arg str]] + +This method causes the character processor to process the character +sequence [arg str], advancing the internal state and invoking action +as necessary. This is a callback for [method listen]. + +[call [arg object] [method eof]] + +This method causes the character processor to handle EOF on the +input. This is currently no-op. + +This is a callback for [method listen]. + +[list_end] + +[section Notes] + +The simplicity of the DFA means that it is not possible to recognize a +character sequence with has a another recognized character sequence as +its prefix. + +[para] + +In other words, the set of recognized strings has to form a +[term {prefix code}]. + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/term/term_send.man b/tcllib/modules/term/term_send.man new file mode 100644 index 0000000..460364b --- /dev/null +++ b/tcllib/modules/term/term_send.man @@ -0,0 +1,36 @@ +[comment {-*- tcl -*- doctools manpage}] +[manpage_begin term::send n 0.1] +[keywords {character output}] +[keywords control] +[keywords terminal] +[copyright {2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] +[moddesc {Terminal control}] +[titledesc {General output to terminals}] +[category {Terminal control}] +[require Tcl 8.4] +[require term::send [opt 0.1]] +[description] + +This package provides the most primitive commands for sending characters +to a terminal. They are in essence convenient wrappers around the +builtin command [cmd puts]. + +[list_begin definitions] +[call [cmd ::term::send::wrch] [arg chan] [arg str]] + +Send the text [arg str] to the channel specified by the handle [arg chan]. +In contrast to the builtin command [cmd puts] this command does not +terminate the string with a line terminator. It also forces an flush of +Tcl internal and OS buffers to ensure that the characters are processed +immediately. + +[call [cmd ::term::send::wr] [arg str]] + +This convenience command is like [cmd ::term::send::wrch], except that the +destination channel is fixed to [emph stdout]. + +[list_end] + +[vset CATEGORY term] +[include ../doctools2base/include/feedback.inc] +[manpage_end] |