URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
[/] [or1k_old/] [trunk/] [insight/] [expect/] [example/] [tkterm] - Rev 1782
Compare with Previous | Blame | View Log
#!../expectk -f
# Name: tkterm - terminal emulator using Expect and Tk text widget, v1.0
# Author: Don Libes, July '94
# This is primarily for regression testing character-graphic applications.
# You can certainly use it as a terminal emulator - however many features
# in a real terminal emulator are not supported (although I'll probably
# add some of them later).
# A paper on the implementation: Libes, D., Automation and Testing of
# Interactive Character Graphic Programs", Software - Practice &
# Experience, John Wiley & Sons, West Sussex, England, Vol. 27(2),
# p. 123-137, February 1997.
###############################
# Quick overview of this emulator
###############################
# Very good attributes:
# Understands both termcap and terminfo
# Understands meta-key (zsh, emacs, etc work)
# Is fast
# Understands X selections
# Looks best with fixed-width font but doesn't require it
# Good-enough-for-starters attributes:
# Understands one kind of standout mode (reverse video)
# Should-be-fixed-soon attributes:
# Does not support scrollbar or resize
# Probably-wont-be-fixed-soon attributes:
# Assumes only one terminal exists
###############################################
# To try out this package, just run it. Using it in
# your scripts is simple. Here are directions:
###############################################
# 0) make sure Expect is linked into your Tk-based program (or vice versa)
# 1) modify the variables/procedures below these comments appropriately
# 2) source this file
# 3) pack the text widget ($term) if you have so configured it (see
# "term_alone" below). As distributed, it packs into . automatically.
#############################################
# Variables that must be initialized before using this:
#############################################
set rows 24 ;# number of rows in term
set cols 80 ;# number of columns in term
set term .t ;# name of text widget used by term
set term_alone 1 ;# if 1, directly pack term into .
;# else you must pack
set termcap 1 ;# if your applications use termcap
set terminfo 1 ;# if your applications use terminfo
;# (you can use both, but note that
;# starting terminfo is slow)
set term_shell $env(SHELL) ;# program to run in term
#############################################
# Readable variables of interest
#############################################
# cur_row ;# current row where insert marker is
# cur_col ;# current col where insert marker is
# term_spawn_id ;# spawn id of term
#############################################
# Procs you may want to initialize before using this:
#############################################
# term_exit is called if the spawned process exits
proc term_exit {} {
exit
}
# term_chars_changed is called after every change to the displayed chars
# You can use if you want matches to occur in the background (a la bind)
# If you want to test synchronously, then just do so - you don't need to
# redefine this procedure.
proc term_chars_changed {} {
}
# term_cursor_changed is called after the cursor is moved
proc term_cursor_changed {} {
}
# Example tests you can make
#
# Test if cursor is at some specific location
# if {$cur_row == 1 && $cur_col == 0} ...
#
# Test if "foo" exists anywhere in line 4
# if {[string match *foo* [$term get 4.0 4.end]]}
#
# Test if "foo" exists at line 4 col 7
# if {[string match foo* [$term get 4.7 4.end]]}
#
# Test if a specific character at row 4 col 5 is in standout
# if {-1 != [lsearch [$term tag names 4.5] standout]} ...
#
# Return contents of screen
# $term get 1.0 end
#
# Return indices of first string on lines 4 to 6 that is in standout mode
# $term tag nextrange standout 4.0 6.end
#
# Replace all occurrences of "foo" with "bar" on screen
# for {set i 1} {$i<=$rows} {incr i} {
# regsub -all "foo" [$term get $i.0 $i.end] "bar" x
# $term delete $i.0 $i.end
# $term insert $i.0 $x
# }
#############################################
# End of things of interest
#############################################
unset env(DISPLAY)
set env(LINES) $rows
set env(COLUMNS) $cols
set env(TERM) "tt"
if $termcap {
set env(TERMCAP) {tt:
:cm=\E[%d;%dH:
:up=\E[A:
:nd=\E[C:
:cl=\E[H\E[J:
:do=^J:
:so=\E[7m:
:se=\E[m:
:k1=\EOP:
:k2=\EOQ:
:k3=\EOR:
:k4=\EOS:
:k5=\EOT:
:k6=\EOU:
:k7=\EOV:
:k8=\EOW:
:k9=\EOX:
}
}
if $terminfo {
set env(TERMINFO) /tmp
set ttsrc "/tmp/tt.src"
set file [open $ttsrc w]
puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
cup=\E[%p1%d;%p2%dH,
cuu1=\E[A,
cuf1=\E[C,
clear=\E[H\E[J,
ind=\n,
cr=\r,
smso=\E[7m,
rmso=\E[m,
kf1=\EOP,
kf2=\EOQ,
kf3=\EOR,
kf4=\EOS,
kf5=\EOT,
kf6=\EOU,
kf7=\EOV,
kf8=\EOW,
kf9=\EOX,
}
close $file
set oldpath $env(PATH)
set env(PATH) "/usr/5bin:/usr/lib/terminfo"
if 1==[catch {exec tic $ttsrc} msg] {
puts "WARNING: tic failed - if you don't have terminfo support on"
puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"."
puts "Here is the original error from running tic:"
puts $msg
}
set env(PATH) $oldpath
exec rm $ttsrc
}
set term_standout 0 ;# if in standout mode or not
log_user 0
# start a shell and text widget for its output
set stty_init "-tabs"
eval spawn $term_shell
stty rows $rows columns $cols < $spawn_out(slave,name)
set term_spawn_id $spawn_id
# this shouldn't be needed if Ousterhout fixes text bug
text $term -relief sunken -bd 1 -width $cols -height $rows -wrap none
if {$term_alone} {
pack $term
}
$term tag configure standout -background black -foreground white
proc term_clear {} {
global term
$term delete 1.0 end
term_init
}
proc term_init {} {
global rows cols cur_row cur_col term
# initialize it with blanks to make insertions later more easily
set blankline [format %*s $cols ""]\n
for {set i 1} {$i <= $rows} {incr i} {
$term insert $i.0 $blankline
}
set cur_row 1
set cur_col 0
$term mark set insert $cur_row.$cur_col
}
proc term_down {} {
global cur_row rows cols term
if {$cur_row < $rows} {
incr cur_row
} else {
# already at last line of term, so scroll screen up
$term delete 1.0 "1.end + 1 chars"
# recreate line at end
$term insert end [format %*s $cols ""]\n
}
}
proc term_insert {s} {
global cols cur_col cur_row
global term term_standout
set chars_rem_to_write [string length $s]
set space_rem_on_line [expr $cols - $cur_col]
if {$term_standout} {
set tag_action "add"
} else {
set tag_action "remove"
}
##################
# write first line
##################
if {$chars_rem_to_write > $space_rem_on_line} {
set chars_to_write $space_rem_on_line
set newline 1
} else {
set chars_to_write $chars_rem_to_write
set newline 0
}
$term delete $cur_row.$cur_col $cur_row.[expr $cur_col + $chars_to_write]
$term insert $cur_row.$cur_col [
string range $s 0 [expr $space_rem_on_line-1]
]
$term tag $tag_action standout $cur_row.$cur_col $cur_row.[expr $cur_col + $chars_to_write]
# discard first line already written
incr chars_rem_to_write -$chars_to_write
set s [string range $s $chars_to_write end]
# update cur_col
incr cur_col $chars_to_write
# update cur_row
if $newline {
term_down
}
##################
# write full lines
##################
while {$chars_rem_to_write >= $cols} {
$term delete $cur_row.0 $cur_row.end
$term insert $cur_row.0 [string range $s 0 [expr $cols-1]]
$term tag $tag_action standout $cur_row.0 $cur_row.end
# discard line from buffer
set s [string range $s $cols end]
incr chars_rem_to_write -$cols
set cur_col 0
term_down
}
#################
# write last line
#################
if {$chars_rem_to_write} {
$term delete $cur_row.0 $cur_row.$chars_rem_to_write
$term insert $cur_row.0 $s
$term tag $tag_action standout $cur_row.0 $cur_row.$chars_rem_to_write
set cur_col $chars_rem_to_write
}
term_chars_changed
}
proc term_update_cursor {} {
global cur_row cur_col term
$term mark set insert $cur_row.$cur_col
term_cursor_changed
}
term_init
set flush 0
proc screen_flush {} {
global flush
incr flush
if {$flush == 24} {
update idletasks
set flush 0
}
# update idletasks
# after 1000 a
}
expect_background {
-i $term_spawn_id
-re "^\[^\x01-\x1f]+" {
# Text
term_insert $expect_out(0,string)
term_update_cursor
} "^\r" {
# (cr,) Go to beginning of line
screen_flush
set cur_col 0
term_update_cursor
} "^\n" {
# (ind,do) Move cursor down one line
term_down
term_update_cursor
} "^\b" {
# Backspace nondestructively
incr cur_col -1
term_update_cursor
} "^\a" {
bell
} "^\t" {
# Tab, shouldn't happen
send_error "got a tab!?"
} eof {
term_exit
} "^\x1b\\\[A" {
# (cuu1,up) Move cursor up one line
incr cur_row -1
term_update_cursor
} "^\x1b\\\[C" {
# (cuf1,nd) Non-destructive space
incr cur_col
term_update_cursor
} -re "^\x1b\\\[(\[0-9]*);(\[0-9]*)H" {
# (cup,cm) Move to row y col x
set cur_row [expr $expect_out(1,string)+1]
set cur_col $expect_out(2,string)
term_update_cursor
} "^\x1b\\\[H\x1b\\\[J" {
# (clear,cl) Clear screen
term_clear
term_update_cursor
} "^\x1b\\\[7m" {
# (smso,so) Begin standout mode
set term_standout 1
} "^\x1b\\\[m" {
# (rmso,se) End standout mode
set term_standout 0
}
}
bind $term <Any-Enter> {
focus %W
}
bind $term <Meta-KeyPress> {
if {"%A" != ""} {
exp_send -i $term_spawn_id "\033%A"
}
}
bind $term <KeyPress> {
exp_send -i $term_spawn_id -- %A
break
}
bind $term <Control-space> {exp_send -null}
bind $term <Control-at> {exp_send -null}
bind $term <F1> {exp_send -i $term_spawn_id "\033OP"}
bind $term <F2> {exp_send -i $term_spawn_id "\033OQ"}
bind $term <F3> {exp_send -i $term_spawn_id "\033OR"}
bind $term <F4> {exp_send -i $term_spawn_id "\033OS"}
bind $term <F5> {exp_send -i $term_spawn_id "\033OT"}
bind $term <F6> {exp_send -i $term_spawn_id "\033OU"}
bind $term <F7> {exp_send -i $term_spawn_id "\033OV"}
bind $term <F8> {exp_send -i $term_spawn_id "\033OW"}
bind $term <F9> {exp_send -i $term_spawn_id "\033OX"}