#!/bin/sh # the next line restarts using expect \ exec expect "$0" -- "$@" # #!/usr/bin/expect -- #!/usr/bin/env expect # (find-node "(sh-utils)env invocation") # (find-man "tclsh" "#!") # # eeg4 and eeg: support for the "generic" interface for eev. # Htmlized version of this file: <http://angg.twu.net/eev-current/eeg4.html>. # Legal stuff: # Copyright (C) 2001-2004 Free Software Foundation, Inc. # Author: Eduardo Ochs <edrx@mat.puc-rio.br> # Maintainer: Eduardo Ochs <edrx@mat.puc-rio.br> # Version: 2004dec29 # 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 ~/eev-current/tmp/ee.eeg) # 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 <enter> 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. # Note, 2004dec29: commented out the code for loadeeglib (see below). # «.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 } proc HOME {} { return getenv HOME } proc EEVDIR {} { return getenv EEVDIR [HOME]/eev-current } proc EEVTMPDIR {} { return getenv EEVTMPDIR [EEVDIR]/tmp } proc EEG {} { return getenv EEG [EEVTMPDIR]/ee.eeg } #### # # «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") # 2004dec29: This is very old code, I haven't used these libraries # ("all" and stuff) in a long time, and I have even removed their code # from the latest versions of eev... I'm commenting out the code # below. # 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") # #### proc doreadscript {} { 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 {} { 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]} {} #L # Local Variables: # mode: tcl # coding: raw-text-unix # ee-anchor-format: "«%s»" # End: