#!/usr/bin/expect -- # eeg4 and eeg: support for the "generic" interface for eev. # Htmlized version of this file: . # Legal stuff: # Copyright (C) 2001 Free Software Foundation, Inc. # Author: Eduardo Ochs # Maintainer: Eduardo Ochs # Version: 2002jan29 # This file was copylefted to prevent against patent psychopaths; if # you want a version with any other license you'll have to write it # yourself. More formally: # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # With this script almost any program that takes input from stdin # becomes e-scriptable. The file $EEG (usually ~/bin/ee.generic) # contains a sequence of "actions"; when we invoke a program through # eeg4 or eeg, with # # eeg4 [options] program [args] # or eeg [options] program [args] # # this script will run "program args" with a bit of keyboard (i.e., # stdin) translation: if we type a "M-l" ("meta-L", which is the Emacs # terminology for an alt-L), eeg4 will capture it and instead of # sending it to the program it will run an action from its list; for # example, in # # cat > $EEG <'---' # echo $shell # exit # --- # eeg tcsh # # the first action will be "send the string 'echo $shell' to the # controlled program, followed by a newline", and the second will be # "send the string 'exit' to the controlled program, followed by a # newline", and so if we run the block above with M-x eev and "ee" and # we type some "M-l"s to eeg we will see something like: # # /home/edrx(edrx)# ee # cat > $EEG <<'---' # echo $shell # exit # --- # eeg tcsh # angg:~# echo $shell # /usr/bin/tcsh # angg:~# exit # exit # /home/edrx(edrx)# # # Compare with what we would see if we had run tcsh and typed "echo # $shell" and "exit" by hand: # # /home/edrx(edrx)# tcsh # angg:~# echo $shell # /usr/bin/tcsh # angg:~# exit # exit # /home/edrx(edrx)# # # but in the first case we only had to type "e e M-l M-l" in # the shell. # # If this script is invoked as "eeg" then each line of $EEG becomes an # action like "send the contents of this line, followed by a newline"; # if it is invoked by any other name (for example, eeg4) then $EEG is # interpreted as a Tcl script; the block # # cat > $EEG <'---' # l {echo $shell} # l {exit} # --- # eeg4 tcsh # # is equivalent to the block used in the example above. # # I have tried to keep this script as minimal as possible; it works # and is useful enough, yet, plus, it has a mechanism for loading # extensions! Take a look at the "loadeeglib" section below and at the # "eeg libraries" that it refers to -- in Tcl it is trivial to replace # a function by just redefining it, so some of the extensions redefine # functions in this file by other, not so minimal, versions. # «.misc» (to "misc") # «.loadeeglib» (to "loadeeglib") # «.actions» (to "actions") # «.dointeraction» (to "dointeraction") # «.actionkey» (to "actionkey") # «.doreadscript» (to "doreadscript") # «.eeg» (to "eeg") # «.dospawn» (to "dospawn") # «.arguments» (to "arguments") # «.mainloop» (to "mainloop") #### # # «misc» (to ".misc") # #### # I/O and generic library functions. proc readfile {fname} { set ch [open $fname r]; set str [read $ch]; close $ch; return $str } proc writefile {fname str} { set ch [open $fname w]; puts -nonewline $ch $str; close $ch } proc getenv {key {defaultvalue {}}} { global env expr {[info exist env($key)]?$env($key):$defaultvalue} } proc ord {str} {scan $str %c n; return $n} proc char {n} {format %c $n} proc gset {args} { uplevel #0 set $args } ;# "global set" # This is to remove a trailing newline, when there is one. proc rmlastnewline {str} { regexp "^(.*)\n\$" $str -> str return $str } #### # # «loadeeglib» (to ".loadeeglib") # #### # (find-angg "eev/libeeg/k") # (find-angg "eev/libeeg/term") # (find-angg "eev/libeeg/msg") # Just add the following to top of your eegscript if you want to load # all the standard extensions and don't want to worry too much about # the details: # # loadeeglibs all ;# (find-angg "eev/libeeg/all") proc toeeglibfname {stem} { return [getenv LIBEEGDIR [getenv HOME]/eev/libeeg]/$stem } proc loadeeglib {stem} { uplevel #0 source [toeeglibfname $stem] } proc loadeeglibs {args} { foreach stem $args {loadeeglib $stem} } #### # # «actions» (to ".actions") # #### set actions {} set actions_i 0 proc doaction {} { global actions actions_i uplevel #0 [lindex $actions $actions_i] incr actions_i } proc appendaction {str} { global actions; lappend actions $str } proc _str {str} { send -- $str } proc str {str} { appendaction [list _str $str] } proc _l {str} { send -- "$str\r" } proc l {str} { appendaction [list _l $str] } #### # # «dointeraction» (to ".dointeraction") # #### set action_re "\354|\033l" proc dointeraction {} { global action_re interact -re $action_re {doaction; inter_return 1} return 0 } #### # # «actionkey» (to ".actionkey") # #### proc meta_re {c} { format "%c|\033%s" [expr [ord $c]+128] $c } proc actionkey {c} { gset action_re [meta_re $c] } #### # # «doreadscript» (to ".doreadscript") # #### set EEG [getenv EEG [getenv HOME]/bin/ee.generic] proc doreadscript {} { global EEG; uplevel #0 source $EEG } # «eeg» (to ".eeg") # A hack: if this script is invoked as "eeg" it will interpret the # $EEG file as a sequence of lines to be sent literally, instead of as # a Tcl script. proc doreadscript_eeg {} { global EEG foreach line [split [rmlastnewline [readfile $EEG]] "\n"] {l $line} } proc eeg {} { proc doreadscript {} { doreadscript_eeg } } if {[file tail $argv0]=="eeg"} eeg #### # # «dospawn» (to ".dospawn") # «arguments» (to ".arguments") # «mainloop» (to ".mainloop") # #### proc dospawn {} { global argv; uplevel #0 spawn -noecho $argv; stty raw } set oldargv $argv while 1 { if {[lindex $argv 0]=="-c"} { uplevel #0 [lindex $argv 1] set argv [lrange $argv 2 end] } if {[lindex $argv 0]=="-f"} { set EEG [lindex $argv 1] set argv [lrange $argv 2 end] } if {$oldargv==$argv} break else {set oldargv $argv} } doreadscript dospawn # The main loop: while {[dointeraction]} {} # # Local Variables: # mode: tcl # coding: no-conversion # ee-anchor-format: "«%s»" # ee-charset-indicator: "Ñ" # End: