Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
;;; eev-steps-mini.el -- minimal versions of the four steppers from eev.

;; Copyright (C) 2006,2007,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 Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;; Author:     Eduardo Ochs <[email protected]>
;; Maintainer: Eduardo Ochs <[email protected]>
;; Version:    2008jul07
;; Keywords:   e-scripts, help, hyperlinks, hypertext, processes,
;;             shell, tex
;;
;; Latest version: <http://angg.twu.net/eev-current/eev-steps-mini.el>
;;       htmlized: <http://angg.twu.net/eev-current/eev-steps-mini.el.html>
;;       See also: <http://angg.twu.net/eev-current/README.html>

;;; Commentary:

;; This file will be merged with "eev-steps.el" at some point,
;; hopefully soon... "eev-steps.el" is much more documented than this,
;; but the code there is a mess; here the names are better, and the
;; functions are much better factored than there.
;;
;; Note that "eev-all.el" loads "eev-mini-steps.el" after
;; "eev-steps.el", and so the definitions from this file will override
;; the definitions from "eev-steps.el" with the same names.

;; (find-eev "eev-steps.el")
;; (find-eev "eev-all.el")
;; (find-eevsh "./eev-rctool")
;; (find-eevsh "./eev-rctool new_block_emacs")

(defun ee-next-line (&optional arg try-vscroll)
"Like `next-line', but always moves by \"buffer lines\".
See: (find-enode \"Moving Point\" \"`line-move-visual'\")\n
Note: the variable `line-move-visual' was introduced in Emacs in
2008jul11. On versions of Emacs older than that this function
behaves exactly like `next-line'."
  (let ((line-move-visual nil))
    (next-line arg try-vscroll)))




;;;            _
;;;   ___  ___| | __
;;;  / _ \/ _ \ |/ /
;;; |  __/  __/   <
;;;  \___|\___|_|\_\
;;;

(defun eek (s &optional e count)
  "Execute the string S (or the region between S and E) as a keyboard macro.
See `edmacro-mode' for the exact format.\n
An example: (eek \"C-x 4 C-h\")"
  (interactive "r")
  (execute-kbd-macro (read-kbd-macro (ee-se-to-string s e)) count))

(defun eek0 (kbmacro &optional count)
  "This is similar to `eek', but uses the low-level formats for macros.
Example: (eek \"\\C-x4\\C-h\")"
  (execute-kbd-macro kbmacro count))





;;;                 _
;;;   ___  ___  ___| |_ ___ _ __  ___
;;;  / _ \/ _ \/ __| __/ _ \ '_ \/ __|
;;; |  __/  __/\__ \ ||  __/ |_) \__ \
;;;  \___|\___||___/\__\___| .__/|___/
;;;                        |_|
;; Steppers - just one, from: (find-eev "eev-steps.el")
;; eek
;; eek0
;; eesteps

(defvar eesteps-list ())
(defvar eesteps-pos  0)

(defun eesteps (list)
  "Set the LIST of steps that `eesteps-do-step' will execute.\n
Here's an example: run\n
  (eesteps '(\"C-x b * scratch * RET   ;;; change to the buffer *scratch*\"
             \"foobar\"
             \"3*<left>\"
             (insert \"!\")))\n
then type \\[eesteps-do-step] four times.\n
Each step is either a string -- meaning a series of keys, in the
format used by `edmacro-mode' -- or a sexp to be evaluated."
  (setq eesteps-pos 0)
  (setq eesteps-list list)
  `(,(length list) steps stored - use <f12> to execute a step))

(defun eesteps-perform (step &rest rest)
  (if (stringp step)
      (eek step)
    (eval step))
  (if rest (apply 'eesteps-perform rest)))

(defun eesteps-do-step (&optional arg)
  (interactive "P")
  (if (>= eesteps-pos (length eesteps-list))
      (error "No more steps"))
  (if (eq arg 0)
      (message "Next step: %d = %S" eesteps-pos (nth eesteps-pos eesteps-list))
    (eesteps-perform (nth eesteps-pos eesteps-list))
    (setq eesteps-pos (1+ eesteps-pos))))




;;;                            _
;;;   ___  ___ _ __   __ _ ___| |_ ___
;;;  / _ \/ _ \ '_ \ / _` / __| __/ _ \
;;; |  __/  __/ |_) | (_| \__ \ ||  __/
;;;  \___|\___| .__/ \__,_|___/\__\___|
;;;           |_|

(defun eepaste-one-line ()
  "Paste (yank) the first line of the top of the kill-ring here and do a RET."
  (interactive)
  (let ((bigstr (car kill-ring)))
    (if (equal bigstr "") (error "No more lines"))
    (string-match "^\\([^\n]*\\)\\(\n\\|$\\)" bigstr)
    (let ((line (match-string 1 bigstr))           ; first line from the kill
	  (rest (substring bigstr (match-end 0)))) ; rest of the kill
      (if (string-match "^*\\(.*\\)" line)         ; lines with a red star
	  (ee-eval-string (match-string 1 line))   ; are eval'ed
	(insert line)			           ; other lines are "typed"
	(call-interactively (key-binding "\r")))   ; and then we do a RET
      (setcar kill-ring rest))))		   ; remove the first line

(defun eestore (s &optional e)
  "Store the region between S and E in the kill ring."
  (kill-new (ee-se-to-string s e))
  (format "Stored in the kill-ring"))

(eeb-define 'eestore-bounded  'eestore 'ee-delimiter-hash  nil t t)




;;;                  _ _       _
;;;   ___  ___ _ __ (_) |_ ___| |__
;;;  / _ \/ _ \ '_ \| | __/ __| '_ \
;;; |  __/  __/ |_) | | || (__| | | |
;;;  \___|\___| .__/|_|\__\___|_| |_|
;;;           |_|
;;
;; The code is quite intricate here, but maybe the diagram below will
;; help... so many functions use the variable `eepitch-target-buffer'
;; that I have not drawn arrows pointing to it.
;;
;;   <f8> ---->   eepitch-this-line
;;                    | |         \ (on "*" lines)
;;        (on non-"*" | |          v
;;             lines) | |           eepitch --------------
;;                    | |          /                       \(set)
;;                    | v         v                  (run)  v
;;                    | eepitch-prepare-target-buffer ---> eepitch-code
;;                    | eepitch-display-target-buffer
;;                    | eepitch-not-this-buffer
;;                    v
;;                 eepitch-line
;;                       |                         eepitch-target-buffer
;;                       v
;;                 (insert line)
;;                 (call-interactively (key-binding "\r"))

(defvar eepitch-code '(error "eepitch not set up"))
(defvar eepitch-target-buffer nil)

(defun eepitch-prepare-target-buffer ()
"Run `eepitch-code' and store the name of the resulting buffer in `eepitch-target-buffer'."
  (save-window-excursion
    (eval eepitch-code)
    (setq eepitch-target-buffer (current-buffer))))

(defun eepitch-display-target-buffer ()
  "Display the buffer `eepitch-target-buffer' in another window."
  (if (not (get-buffer-window eepitch-target-buffer))
      (let ((pop-up-windows t)
	    (same-window-buffer-names nil))
	(display-buffer eepitch-target-buffer))))

(defun eepitch (code)
"Set the target buffer for pitching lines to; CODE is something like `(shell)'.
To pitch lines to the target buffer, use `\\[eepitch-this-line]'.
As with `eechannel', lines starting with `*' are executed as Lisp;
other lines are sent.

There's a (trivial) example of usage below; each line is meant to
be executed with `\\[eepitch-this-line]'. For a convenient way to
generate the three \"*\" lines at once - by typing just \"shell\"
and then `\\[ee-wrap-eepitch]' - see `ee-wrap-eepitch' and
`eepitch-shell'.

* (eepitch '(shell))
* (eepitch-kill)
* (eepitch '(shell))
cd /tmp/
pwd
"
  (if (not (listp code))
      (error "eepitch is no longer a macro - quote the code!"))
  (setq eepitch-code code)
  (eepitch-prepare-target-buffer)
  (eepitch-display-target-buffer))

(defun eepitch-line (line)
  (save-selected-window
    (select-window (get-buffer-window eepitch-target-buffer))
    (insert line)                              ; "type" the line
    (call-interactively (key-binding "\r"))))  ; then do a RET

(defun eepitch-not-this-buffer ()
  (if (eq (current-buffer) eepitch-target-buffer)
      (error "Can't pitch to the current buffer")))

(defun eepitch-this-line ()
"Pitch this line to the target buffer, or eval it as lisp if it starts with `*'.
See `eepitch' and the source code."
  (interactive)
  (let ((line (buffer-substring (ee-bol) (ee-eol)))) ; contents of this line
    (if (string-match "^*\\(.*\\)" line)             ; lines with a red star
        (ee-eval-string (match-string 1 line))       ; are eval'ed -
      (eepitch-prepare-target-buffer)	 ; for other lines reconstruct the
      (eepitch-display-target-buffer)	 ; target buffer, display it, make
      (eepitch-not-this-buffer)		 ; sure it's a different buffer, and
      (eepitch-line line)))		 ; pitch the line to the target.
  (ee-next-line 1))

(defun eepitch-kill ()
  "Kill the `eepitch-target-buffer'. See `eepitch' and the source code."
  (interactive)
  (eepitch-prepare-target-buffer)	 ; Prepare (maybe reconstruct) the
  (eepitch-display-target-buffer)	 ; target buffer, display it, make
  (eepitch-not-this-buffer)		 ; sure it's a different buffer...
  (save-selected-window			 ; Then temporarily switch to the
    (select-window (get-buffer-window eepitch-target-buffer)) ; right window,
    (ee-kill-this-buffer)))		 ; and kill the buffer that is there.




;; convenience

(defun eepitch-comint (name program-and-args)
"Set `eepitch' to run PROGRAM-AND-ARGS in comint mode, in the buffer \"*NAME*\"."
  (eepitch `(find-comintprocess ,name ',program-and-args)))

(defun eepitch-shell ()
  "Same as (eepitch '(shell)). See `eepitch' and `ee-wrap-eepitch'."
  (interactive)
  (eepitch '(shell)))

(defun eepitch-shell2  () (interactive) (eepitch '(shell "*shell 2*")))
(defun eepitch-eshell  () (interactive) (eepitch '(eshell)))
(defun eepitch-lua51   () (interactive) (eepitch-comint "lua51"   "lua51"))
(defun eepitch-python  () (interactive) (eepitch-comint "python"  "python"))
(defun eepitch-ruby    () (interactive) (eepitch-comint "ruby"    "irb1.8"))
(defun eepitch-gnuplot () (interactive) (eepitch-comint "gnuplot" "gnuplot"))
(defun eepitch-wish    () (interactive) (eepitch-comint "wish"    "wish"))
(defun eepitch-tcl     () (interactive) (eepitch-comint "tclsh"   "tclsh"))
(defun eepitch-tclsh   () (interactive) (eepitch-comint "tclsh"   "tclsh"))
(defun eepitch-expect  () (interactive) (eepitch-comint "expect"  "expect"))
(defun eepitch-gforth  () (interactive) (eepitch '(run-forth "gforth")))


;; Added in 2008jan10:
(defun ee-eepitch-comint (dir name program-and-args)
  "Like `eepitch-comint', but run PROGRAM-AND-ARG at the directory DIR.
DIR is expanded with `ee-expand'; the result of the expansion
must be absolute, and must end with a slash."
  (eepitch `(ee-find-comintprocess (ee-expand ,dir) ,name ',program-and-args)))

(defun eepitch-latex () (interactive) (ee-eepitch-comint "/tmp/" "latex" "latex"))
(defun eepitch-tex   () (interactive) (ee-eepitch-comint "/tmp/" "tex"   "tex"))
(defun eepitch-mf    () (interactive) (ee-eepitch-comint "/tmp/" "mf"   "mf"))



;;;                  _ _       _                     _ _
;;;   ___  ___ _ __ (_) |_ ___| |__         __ _  __| | |__
;;;  / _ \/ _ \ '_ \| | __/ __| '_ \ _____ / _` |/ _` | '_ \
;;; |  __/  __/ |_) | | || (__| | | |_____| (_| | (_| | |_) |
;;;  \___|\___| .__/|_|\__\___|_| |_|      \__, |\__,_|_.__/
;;;           |_|                          |___/
;;;
;; 2007dec14: This is immature code, but it is very useful... see:
;;   http://article.gmane.org/gmane.emacs.eev.devel/47
;;   http://lists.gnu.org/archive/html/eev/2007-07/msg00000.html
;; Layout:
;;    ______________________
;;   |           |	    |
;;   | e-script  |	    |
;;   |  buffer   |  source  |
;;   |___________|   code   |
;;   |           |  buffer  |
;;   |   gdb     |	    |
;;   |  buffer   |	    |
;;   |___________|__________|
;; This will probably make the `eegud-*' functions in "eev-langs.el"
;; obsolete very soon.
;;   (find-eev "eev-langs.el")
;;   (find-efunction 'eegud-keys-mode)
;;   http://angg.twu.net/eev-current/eev-langs.el.html#eegud-keys-mode
;; HELP NEEDED: there's a new interface for gdb that I don't know how
;; to use... see: (find-enode "GDB-UI Layout")
;; There's a screenshot of it at:
;;   http://www.gnu.org/software/emacs/tour/
;;   http://www.gnu.org/software/emacs/tour/images/gdb.png

(define-key eegud-keys-mode-map "\M-k" 'eegud-kill-this-buffer)

(defun eegud-kill-this-buffer ()
  (interactive)
  (delete-other-windows)
  (ee-kill-this-buffer))

(defvar ee-gud-escript-window nil
  "An internal variable used to simplify the code of `eepitch-gdb'.
The \"e-script window\" is the upper-left quadrant of the frame.")

(defvar ee-gud-gud-window nil
  "An internal variable used to simplify the code of `eepitch-gdb'.
The \"gud window\" is the lower-left quadrant of the frame.")

(defvar ee-gud-source-window nil
  "An internal variable used to simplify the code of `eepitch-gdb'.
The \"source window\" is the right half of the frame.")

(defun eepitch-gud-window-setup ()
  (interactive)
  (delete-other-windows)
  (split-window-horizontally)  ; left|right
  (split-window-vertically)    ; split the left side into upper/lower
  (setq ee-gud-escript-window (selected-window)) ; upper left
  (setq ee-gud-gud-window     (next-window))	 ; lower left
  (setq ee-gud-source-window  (next-window (next-window)))) ; right

(defun eepitch-gdb (buffer-name gdb-prog-and-args)
  (eepitch-gud-window-setup)
  (with-selected-window ee-gud-gud-window
    (if (get-buffer buffer-name)
	(find-ebuffer buffer-name)
      (gdb gdb-prog-and-args)
      (eegud-keys-mode 1)))
  (setq eepitch-code `(find-ebuffer ,buffer-name)))

(defun eepitch-gdb-kill (buffer-name)
  (if (get-buffer buffer-name) (kill-buffer buffer-name))
  (delete-other-windows))

'(
;; An example of usage:
;; see: (find-es "lua5" "compile-5.1.2-lua_O0")
;; http://angg.twu.net/e/lua5.e.html#compile-5.1.2-lua_O0
;; This example should be moved to somewhere else...

(defun eepitch-gdb-lua ()
  (eepitch-gdb "*gud-lua" "gdb --annotate=3 --quiet ~/usrc/lua-5.1.2/src/lua"))
(defun eepitch-gdb-lua-kill ()
  (eepitch-gdb-kill "*gud-lua"))

(defun eepitch-gdb-lua ()
  (eepitch-gdb "*gud-lua_O0*" "gdb --annotate=3 --quiet ~/usrc/lua-5.1.2/src/lua_O0"))
(defun eepitch-gdb-lua-kill ()
  (eepitch-gdb-kill "*gud-lua_O0*"))

* (eepitch-gdb-lua)
* (eepitch-gdb-lua-kill)
* (eepitch-gdb-lua)
br main
run
n

) ;; end of the example






;;;                 _                            _
;;;   ___  ___  ___| |__   __ _ _ __  _ __   ___| |
;;;  / _ \/ _ \/ __| '_ \ / _` | '_ \| '_ \ / _ \ |
;;; |  __/  __/ (__| | | | (_| | | | | | | |  __/ |
;;;  \___|\___|\___|_| |_|\__,_|_| |_|_| |_|\___|_|
;;;
;; (find-man "xterm" "-T string")
;; (find-man "xterm" "-e program [ arguments ... ]")
;; (find-eev "eegchannel")
;; (find-eev "eegchannel" "pidfile")
;; (find-eev "eegchannel" "strfile")
;;
;; There is a big diagram explaining how this works at:
;;
;;   (find-eev "anim/channels.anim")
;;
;; Note that this is a "communication diagram" - it shows which
;; programs start which other programs, and how they communicate.
;; Here is a call diagram for the lisp functions (and some
;; variables):
;;
;;   <F9> ---> eechannel-this-line
;;                    |          \ (on "*" lines)
;;        (on non-"*" |           v 
;;             lines) |            ee-eval-string 
;;                    v
;;             eechannel-send          
;;              |  |  |                
;;              |  |  v                  (sets)
;;              |  v eechannel-default  <------ eechannel
;;              v eechannel-strfile
;;       /---> eechannel-pid ----------> eechannel-pidfile
;;       |
;;      eechannel-kill

(defvar eechannel-default nil)

(defun eechannel-strfile (channel)
  (ee-expand (format "$EEVTMPDIR/eeg.%s.str" channel)))

(defun eechannel-pidfile (channel)
  (ee-expand (format "$EEVTMPDIR/eeg.%s.pid" channel)))

(defun eechannel-pid     (channel)
"Return the pid stored in the eeg.CHANNEL.pid file, as a string (or nil on error)."
  (let ((pidfile (eechannel-pidfile channel)))
    (if (file-exists-p pidfile)
	(ee-no-trailing-nl (ee-read-file pidfile)))))

(defun eechannel-kill (channel sig)
  "Send the signal SIG to the process listening on the channel CHANNEL."
  ;; We call "kill" to send the signal.
  (find-callprocess0 (format "kill %s %s" sig (eechannel-pid channel))))

(defun eechannel-send (channel str)
  "Send STR through channel CHANNEL (or through channel `eechannel-default')."
  (setq channel (or channel eechannel-default))
  (write-region str nil (eechannel-strfile channel))
  (find-callprocess0 (format "kill -USR1 %s" (eechannel-pid channel))))

(defun eechannel-this-line () (interactive)
  "Send the current line through the channel `eechannel-default', and go down.
If the line starts with a `*' then evaluate it as lisp instead of sending it."
  (let ((line (buffer-substring (ee-bol) (ee-eol)))) ; contents of this line
    (if (string-match "^*\\(.*\\)" line)             ; lines with a red star
	(ee-eval-string (match-string 1 line))       ; are eval'ed
      (eechannel-send nil (concat line "\n")))       ; other lines are sent
    (ee-next-line 1)))			             ; go down

(defun eechannel (channel)
  "Set the default channel to CHANNEL."
  (interactive "sDefault channel: ")
  (setq eechannel-default channel))




;;;                 _                                   _
;;;   ___  ___  ___| |__         __ _ ___ ___  ___ _ __| |_
;;;  / _ \/ _ \/ __| '_ \ _____ / _` / __/ __|/ _ \ '__| __|
;;; |  __/  __/ (__| | | |_____| (_| \__ \__ \  __/ |  | |_
;;;  \___|\___|\___|_| |_|      \__,_|___/___/\___|_|   \__|
;;;

(defun eechannel-pid-running-p (pid)
  "Return t if a process with pid PID is running. This is linux-specific."
  ;; I've heard the on BSDs "/proc" is optional and often disabled...
  ;; Calling "ps" every time sounds expensive, what should I do?
  (file-exists-p (format "/proc/%s" pid)))

;; The six functions below are for when we want to use eegchannel
;; directly, without calling it from an xterm (as in eexterm)...

(defun eechannel-args-ne (channel prog-and-args)
  `(,(ee-expand "$EEVDIR/eegchannel") ,channel
    ,@(ee-split prog-and-args)))

(defun eechannel-create-ne (channel prog-and-args)
  (find-bgprocess-ne (eechannel-args-ne channel prog-and-args)))

(defun eechannel-assert-ne (channel prog-and-args)
  (let ((pid (eechannel-pid channel)))
    (if (eechannel-pid-running-p (eechannel-pid channel))
	(message "Channel %s (pid %s) looks alive, reusing" channel pid)
      (eechannel-create-ne channel prog-and-args))))

(defun eechannel-args   (channel prog-and-args)
  (eechannel-args-ne   channel (ee-split-and-expand prog-and-args)))
(defun eechannel-create (channel prog-and-args)
  (eechannel-create-ne channel (ee-split-and-expand prog-and-args)))
(defun eechannel-assert (channel prog-and-args)
  (eechannel-assert-ne channel (ee-split-and-expand prog-and-args)))




;;;                 _
;;;   ___  _____  _| |_ ___ _ __ _ __ ___
;;;  / _ \/ _ \ \/ / __/ _ \ '__| '_ ` _ \
;;; |  __/  __/>  <| ||  __/ |  | | | | | |
;;;  \___|\___/_/\_\\__\___|_|  |_| |_| |_|
;;;
;; A call diagram:
;;
;;   eexterm ---------> eexterm-ne      
;;                        |    |       
;;                        |    v       
;;                        |  eechannel-pid-running-p
;;                        v             
;;   eexterm-create --> eexterm-create-ne    
;;                        |             
;;                        v             
;;   eexterm-args ----> eexterm-args-ne      
;;
;;   eexterm-kill -----> eechannel-kill

(defun eexterm-args-ne (channel prog-and-args xterm-args)
"Return a list of arguments for running a xterm listening on CHANNEL.
Try these examples:
  (eexterm-args-ne \"A\" nil nil)
  (eexterm-args-ne \"A\" '(\"ssh\" \"foo@bar\") \"-geometry 80x20\")"
  `("xterm"
    "-T" ,(format "channel %s" channel)
    ,@(ee-split xterm-args)
    "-e" ,(ee-expand "$EEVDIR/eegchannel") ,channel
    ,@(ee-split (or prog-and-args (ee-expand "$SHELL")))))

(defun eexterm-create-ne (channel prog-and-args xterm-args)
  "Start a xterm listening on CHANNEL. See `eexterm-args-ne'."
  (find-bgprocess-ne (eexterm-args-ne channel prog-and-args xterm-args)))

(defun eexterm-ne (channel prog-and-args xterm-args)
"Set the default channel to CHANNEL; create an xterm listening on CHANNEL if needed."
  (interactive "sDefault channel: ")
  (setq eechannel-default channel)
  (if (eechannel-pid-running-p (eechannel-pid channel))
      (message "Reusing xterm at channel %s" channel)
    (eexterm-create-ne channel prog-and-args xterm-args)))

(defun eexterm-args   (channel &optional prog-and-args xterm-args)
  (eexterm-args-ne   channel (ee-split-and-expand prog-and-args) xterm-args))
(defun eexterm-create (channel &optional prog-and-args xterm-args)
  (eexterm-create-ne channel (ee-split-and-expand prog-and-args) xterm-args))
(defun eexterm        (channel &optional prog-and-args xterm-args)
"Set the default channel to CHANNEL; create an xterm listening on CHANNEL if needed."
  (interactive "sDefault channel: ")
  (eexterm-ne        channel (ee-split-and-expand prog-and-args) xterm-args))

(defalias 'eechannel-xterm 'eexterm)

(defun eexterm-kill (&optional channel sig)
  (interactive)
  (eechannel-kill (or channel eechannel-default) (or sig "")))



'(

;; obsolete versions:
(defun eexterm-create (channel &optional prog-and-args xterm-args)
  "Create an xterm listening on CHANNEL."
  (interactive "sChannel: ")
  (find-bgprocess-ne
   `("xterm"
     "-T" ,(format "channel %s" channel)
     ,@xterm-args
     "-e" ,(ee-expand "$EEVDIR/eegchannel") ,channel
     ,@(or prog-and-args (list (ee-expand "$SHELL"))))))

(defun eexterm (channel &optional prog-and-args xterm-args)
"Set the default channel to CHANNEL; create an xterm listening on CHANNEL if needed."
  (interactive "sDefault channel: ")
  (setq eechannel-default channel)
  (if (eechannel-pid-running-p (eechannel-pid channel))
      (message "Reusing xterm at channel %s" channel)
    (eexterm-create channel prog-and-args xterm-args)))

)






;; extras - cannibalize and discard the rest

;; ...
;; CODE is typically a hyperlink to a comint buffer, like in:
;;   (eepitch (shell))
;; or in:

;; (find-efunction 'eepitch-this-line)
;; (find-efunction 'eepitch)

'(

(defun eechannel-running-p (channel)
  "Returns t if there is a process listening on CHANNEL."
  (let ((pid (eechannel-pid channel)))
    (if pid (ee-pid-running-p pid))))

(defun eech (s &optional e)		; bad name?
  (interactive "r")
  (eechannel-send eechannel-default (ee-se-to-string s e)))

(eeb-define 'eech-bounded 'eech 'ee-delimiter-hash nil t t)

(defun eechannel-xterm (channel &optional prog-and-args xterm-args)
"Set the default channel to CHANNEL; create an xterm listening on CHANNEL if needed."
  (interactive "sChannel: ")
  (eechannel channel)
  (if (eechannel-running-p channel)
      (message "Reusing channel %s" channel)
    (eebg-channel-xterm channel prog-and-args xterm-args)))

(defun eechannel-kill (channel)
  "Kill the process associated to channel CHANNEL."
  (find-sh0 (format "kill -9 $(cat %s)" (eechannel-pidfile channel))))

)



(provide 'eev-mini-steps)


;; Local Variables:
;; coding:           raw-text-unix
;; ee-anchor-format: "defun %s "
;; no-byte-compile:  t
;; End: