Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
#!/bin/sh
# the next line restarts using expect \
exec expect "$0" -- "$@"
# (find-man "1 tclsh" "#!")
# eeg4 and eeg: support for the "generic" interface for eev.

proc COPYRIGHT {} { puts {\
This is the `eeg4' file of GNU eev (and also the `eeg' file, due to a link).

Copyright (C) 2001,2002,2003,2004,2005,2008 Free Software Foundation, Inc.

This file is part of GNU eev.

GNU eev 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, or (at your option) any
later version.

GNU eev is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GNU eev; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

Author:     Eduardo Ochs <eduardoochs@gmail.com>
Maintainer: Eduardo Ochs <eduardoochs@gmail.com>
Version:    2008jul03
}}

### Comment:

# eeg4 and eeg: support for the "generic" interface for eev.
# Keywords:     e-scripts, processes
#
# Latest version: <http://angg.twu.net/eev-current/eeg4>
#       htmlized: <http://angg.twu.net/eev-current/eeg4.html>
#       See also: <http://angg.twu.net/eev-current/README.html>
#            and: <http://angg.twu.net/eev-current/eegchannel.html>

# 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      {} { getenv HOME }
proc EEVDIR    {} { getenv EEVDIR    [HOME]/eev-current }
proc EEVTMPDIR {} { getenv EEVTMPDIR [EEVDIR]/tmp }
proc EEG       {} { 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 env(EEG) [lindex $argv 1]; # QUICK HACK, AFFECTS SUB-"eeg"S! FIX THIS!
    set argv [lrange $argv 2 end]
  }
  if {$oldargv==$argv} break else {set oldargv $argv}
}

doreadscript
dospawn

# Code for SIGWINCH added in 2005jan08.
# Transmit resizings. From <http://www.hadron.org/~hatch/goodies/rrr>.
trap {
  stty rows [stty rows] columns [stty columns] < $spawn_out(slave,name)
} WINCH


# The main loop:
while {[dointeraction]} {}




#
#  Local Variables:
#  mode:		 tcl
#  coding:               raw-text-unix
#  ee-anchor-format:     "«%s»"
#  End: