OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [expect/] [example/] [virterm] - Rev 1776

Go to most recent revision | Compare with Previous | Blame | View Log

#!../expect --

# Name: virterm - terminal emulator using Expect, v1.0, December, 1994
# Author: Adrian Mariano <adrian@cam.cornell.edu>
#
# Derived from Done Libes' tkterm

# This is a program for interacting with applications that use terminal
# control sequences.  It is a subset of Don Libes' tkterm emulator
# with a compatible interface so that programs can be written to work 
# under both.  
# 
# Internally, it uses arrays instead of the Tk widget.  Nonetheless, this
# code is not as fast as it should be.  I need an Expect profiler to go
# any further.
#
# standout mode is not supported like it is in tkterm.  
# the only terminal widget operation that is supported for the user
# is the "get" operation.  
###############################################
# 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 myterm         ;# name of text widget used by term
set termcap 1           ;# if your applications use termcap
set terminfo 0          ;# 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 associated proc 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]]}
#
# Return contents of screen
# $term get 1.0 end

#############################################
# End of things of interest
#############################################

set blankline ""
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:
        :cl=\E[H\E[J:
        :do=^J:
        :so=\E[7m:
        :se=\E[m:
        :nd=\E[C:
    }
}

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,
    }
    close $file

    set oldpath $env(PATH)
    set env(PATH) "/usr/5bin:/usr/lib/terminfo"
    if 1==[catch {exec tic $ttsrc} msg] {
        puts "WARNING: puts "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
}

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

proc term_replace {reprow repcol text} {
  global termdata
  set middle $termdata($reprow) 
  set termdata($reprow) \
     [string range $middle 0 [expr $repcol-1]]$text[string \
       range $middle [expr $repcol+[string length $text]] end]
}


proc parseloc {input row col} {
  upvar $row r $col c
  global rows
  switch -glob -- $input \
    end { set r $rows; set c end } \
    *.* { regexp (.*)\\.(.*) $input dummy r c
           if {$r == "end"} { set r $rows }
        }
}

proc myterm {command first second args} {
  global termdata
  if {[string compare get $command]} { 
    send_error "Unknown terminal command: $command\r"
  } else {
    parseloc $first startrow startcol
    parseloc $second endrow endcol
    if {$endcol != "end"} {incr endcol -1}
    if {$startrow == $endrow} { 
      set data [string range $termdata($startrow) $startcol $endcol]
    } else {
      set data [string range $termdata($startrow) $startcol end]
      for {set i [expr $startrow + 1]} {$i < $endrow} {incr i} {
        append data $termdata($i)
      }
      append data [string range $termdata($endrow) 0 $endcol]
    }
    return $data
  }
}


proc scrollup {} {
  global termdata blankline
  for {set i 1} {$i < $rows} {incr i} {
    set termdata($i) $termdata([expr $i+1]) 
  }
  set termdata($rows) $blankline
}


proc term_init {} {
        global rows cols cur_row cur_col term termdata blankline
        
        # initialize it with blanks to make insertions later more easily
        set blankline [format %*s $cols ""]\n
        for {set i 1} {$i <= $rows} {incr i} {
             set termdata($i) "$blankline"
        }

        set cur_row 1
        set cur_col 0
}


proc term_down {} {
        global cur_row rows cols term

        if {$cur_row < $rows} {
                incr cur_row
        } else {
                scrollup
        }
}


proc term_insert {s} {
        global cols cur_col cur_row term

        set chars_rem_to_write [string length $s]
        set space_rem_on_line [expr $cols - $cur_col]

        ##################
        # write first line
        ##################

        if {$chars_rem_to_write <= $space_rem_on_line} {
           term_replace $cur_row $cur_col \
              [string range $s 0 [expr $space_rem_on_line-1]]
           incr cur_col $chars_rem_to_write
           term_chars_changed
           return
        }

        set chars_to_write $space_rem_on_line
        set newline 1

        term_replace $cur_row $cur_col\
            [string range $s 0 [expr $space_rem_on_line-1]]

        # 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_replace $cur_row 0 [string range $s 0 [expr $cols-1]]

                # 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_replace $cur_row 0 $s
                set cur_col $chars_rem_to_write
        }

        term_chars_changed
}

term_init

expect_before {
        -i $term_spawn_id
        -re "^\[^\x01-\x1f]+" {
                # Text
                term_insert $expect_out(0,string)
                term_cursor_changed
        } "^\r" {
                # (cr,) Go to to beginning of line
                set cur_col 0
                term_cursor_changed
        } "^\n" {
                # (ind,do) Move cursor down one line
                term_down
                term_cursor_changed
        } "^\b" {
                # Backspace nondestructively
                incr cur_col -1
                term_cursor_changed
        } "^\a" {
                # Bell, pass back to user
                send_user "\a"
        } "^\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_cursor_changed
        } "^\x1b\\\[C" {
                # (cuf1,nd) Nondestructive space
                incr cur_col
                term_cursor_changed
        } -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_cursor_changed
        } "^\x1b\\\[H\x1b\\\[J" {
                # (clear,cl) Clear screen
                term_init
                term_cursor_changed
        } "^\x1b\\\[7m" { # unsupported
                # (smso,so) Begin standout mode
                # set term_standout 1
        } "^\x1b\\\[m" {  # unsupported
                # (rmso,se) End standout mode
                # set term_standout 0
        }
}


proc term_expect {args} {
        global cur_row cur_col  # used by expect_background actions

        set desired_timeout [
            uplevel {
                if [info exists timeout] {
                        set timeout
                } else {
                        uplevel #0 {
                                if {[info exists timeout]} {
                                        set timeout
                                } else {
                                        expr 10
                                }
                        }
                }
            }
        ]

        set timeout $desired_timeout

        set timeout_act {}

        set argc [llength $args]
        if {$argc%2 == 1} {
                lappend args {}
                incr argc
        }

        for {set i 0} {$i<$argc} {incr i 2} {
                set act_index [expr $i+1]
                if {[string compare timeout [lindex $args $i]] == 0} {
                        set timeout_act [lindex $args $act_index]
                        set args [lreplace $args $i $act_index]
                        incr argc -2
                        break
                }
        }

        set got_timeout 0
        
        set start_time [timestamp]

        while {![info exists act]} {
                expect timeout {set got_timeout 1}
                set timeout [expr $desired_timeout - [timestamp] + $start_time]
                if {! $got_timeout} \
                {
                        for {set i 0} {$i<$argc} {incr i 2} {
                                if {[uplevel [lindex $args $i]]} {
                                        set act [lindex $args [incr i]]
                                        break
                                }
                        }
                } else { set act $timeout_act }

                if {![info exists act]} {

                }
        }

        set code [catch {uplevel $act} string]
        if {$code >  4} {return -code $code $string}
        if {$code == 4} {return -code continue}
        if {$code == 3} {return -code break}
        if {$code == 2} {return -code return}
        if {$code == 1} {return -code error -errorinfo $errorInfo \
                                -errorcode $errorCode $string}
        return $string
}       


# ======= end of terminal emulator ========

# The following is a program to interact with the Cornell Library catalog


proc waitfornext {} {
  global cur_row cur_col term
  term_expect {expr {$cur_col==15 && $cur_row == 24 &&
                         " NEXT COMMAND:  " == [$term get 24.0 24.16]}} {}
}

proc sendcommand {command} {
  global cur_col
  exp_send $command
  term_expect {expr {$cur_col == 79}} {}
}

proc removespaces {intext} {
  regsub -all " *\n" $intext \n intext
  regsub "\n+$" $intext \n intext
  return $intext
}

proc output {text} {
  exp_send_user $text
}



proc connect {} {
  global term
  term_expect {regexp {.*[>%]} [$term get 1.0 3.end]}
  exp_send "tn3270 notis.library.cornell.edu\r"
  term_expect {regexp "desk" [$term get 19.0 19.end]} {
                  exp_send "\r"
        } 
  waitfornext
  exp_send_error "connected.\n\n"
}


proc dosearch {search} {
  global term
  exp_send_error "Searching for '$search'..."
  if [string match ?=* "$search"] {set typ ""} else {set typ "k="}
  sendcommand "$typ$search\r"
  waitfornext
  set countstr [$term get 2.17 2.35]
  if {![regsub { Entries Found *} $countstr "" number]} {
    set number 1
    exp_send_error "one entry found.\n\n"
    return 1
  }
  if {$number == 0} {
    exp_send_error "no matches.\n\n"
    return 0
  }
  exp_send_error "$number entries found.\n"
  if {$number > 250} {
    exp_send_error "(only the first 250 can be displayed)\n"
  }
  exp_send_error "\n"
  return $number
}


proc getshort {count} {
  global term
  output [removespaces [$term get 5.0 19.0]]
  while {[regexp "CONTINUED on next page" [$term get 19.0 19.end]]} {
    sendcommand "for\r"
    waitfornext
    output [removespaces [$term get 5.0 19.0]]
  }
}

proc getonecitation {} {
  global term
  output [removespaces [$term get 4.0 19.0]]
  while {[regexp "FORward page" [$term get 20.0 20.end]]} {
    sendcommand "for\r"
    waitfornext
    output [removespaces [$term get 5.0 19.0]]
  }
}


proc getcitlist {} {
  global term
  getonecitation
  set citcount 1
  while {[regexp "NEXt record" [$term get 20.0 21.end]]} {
    sendcommand "nex\r"
    waitfornext
    getonecitation
    incr citcount
    if {$citcount % 10 == 0} {exp_send_error "$citcount.."}
  }
}

proc getlong {count} {
  if {$count != 1} {
    sendcommand "1\r"
    waitfornext
  }
  sendcommand "lon\r"
  waitfornext
  getcitlist
}

proc getmed {count} {
  if {$count != 1} {
    sendcommand "1\r"
    waitfornext
  }
  sendcommand "bri\r"
  waitfornext
  getcitlist
}
  
#################################################################
#
set help {
libsearch version 1.0 by Adrian Mariano (adrian@cam.cornell.edu)

Invocation: libsearch [options] search text

 -i      : interactive
 -s      : short listing
 -l      : long listing
 -o file : output file (default stdout)
 -h      : print out list of options and version number
 -H      : print terse keyword search help

The search will be a keyword search.  
Example:  libsearch -i sound and arabic

}

#################################################################

proc searchhelp {} {
  send_error {
? truncation wildcard            default operator is AND

AND - both words appear in record
OR  - one of the words appears
NOT - first word appears, second words does not
ADJ - words are adjacent
SAME- words appear in the same field (any order)

.su. - subject   b.fmt. - books    eng.lng. - English  
.ti. - title     m.fmt. - music    spa.lng. - Spanish
.au. - author    s.fmt. - serials  fre.lng. - French

.dt. or .dt1. -- limits to a specific publication year.  E.g., 1990.dt.

}
}

proc promptuser {prompt} {
  exp_send_error "$prompt"
  expect_user -re "(.*)\n"
  return "$expect_out(1,string)"
}


set searchtype 1  
set outfile ""
set search ""
set interactive 0

while {[llength $argv]>0} {
  set flag [lindex $argv 0]
  switch -glob -- $flag \
   "-i" { set interactive 1; set argv [lrange $argv 1 end]} \
   "-s" { set searchtype 0; set argv [lrange $argv 1 end] } \
   "-l" { set searchtype 2; set argv [lrange $argv 1 end] } \
   "-o" { set outfile [lindex $argv 1]; set argv [lrange $argv 2 end] } \
   "-H" { searchhelp; exit } \
   "-h" { send_error "$help"; exit } \
   "-*" { send_error "\nUnknown option: $flag\n$help";exit }\
   default { set search [join $argv]; set argv {};}
}  
if { "$search" == "" } {
  send_error "No search specified\n$help"
  exit
}

exp_send_error "Connecting to the library..."

set timeout 200

trap { log_user 1;exp_send "\003";
       expect_before
       expect tn3270 {exp_send "quit\r"}
       expect "Connection closed." {exp_send "exit\r"}
       expect eof ; send_error "\n"; 
       exit} SIGINT


connect

set result [dosearch $search]

if {$interactive} {
  set quit 0
  while {!$quit} {
    if {!$result} {
      switch "[promptuser {(h)elp (n)ewsearch (q)uit? }]" {
        n { }
        h { searchhelp }
        q { set quit 1}
      }
    } else {
   switch "[promptuser {(s)hort (m)ed (l)ong (h)elp (n)ewsearch (q)uit? }]" {
        s { getshort $result; ;}
        l { getlong $result; ;}
        m { getmed $result; ; }
        n { research; }
        h { searchhelp }
        q { set quit 1; }
      }
    }
  }
} else {
  if {$result} {
    switch $searchtype {
      0 { getshort $result} 
      1 { getmed $result  } 
      2 { getlong $result }
    }
  }
}






Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.