Subject: [clisp-list] RFE: debugging in separate window

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Fri Apr 11 09:49:07 2003

Hi,

please have a short look at impnotes:
Extensions-2.12. Other
To have *DEBUG-IO* and *ERROR-OUTPUT* point to separate console windows (thus keeping your standard console window clean from error messages) you can use:
       (SETQ *ERROR-OUTPUT*
         (SETQ *DEBUG-IO*
           (OPEN "CON:0/0/500/300/CLISP-Debugger/AUTO/CLOSE"
                   :DIRECTION :IO)))

I don't know if people on UNIX/PC realize the power and usefulness of this.
I wish I could use this idiom on UNIX or MS-Windows too, not just the Amiga.

On the Amiga, CON:////window-title/options provides for a full-featured tty-window with line-editing and scrollbars etc. The above means sort of *debug-io* goes to a separate xterm window. The given options mean that this window only appears when needed (e.g. when an error occurs).

Consider CLISP within a shell pipe
# cat foo bar | clisp --with-interactive-debug -i file -x ... | xyz-processing

Using the above with a pipe means that Lisp's *standard-input* and -output* are left completely undisturbed!
All your *debug-io* interactive session happens in a different window. There you can either abort CLISP and thus the pipe, or maybe manage to debug online and have the pipe continue successfully.

Bruno Haible once told me about a UNIX terminal/xterm hack where output to stderr would appear in red color.

I often send *trace-output* to a separate window.

You get the idea.

Does anybody know how to achieve something equivalent for either MS-Windows or some flavour of UNIX?

Regards,
	Jörg Höhle.

---

From: Michael Koehne <[email-masked]>
Date: Fri Apr 11 10:23:16 2003

Moin Joerg-Cyril Hoehle,

> I wish I could use this idiom on UNIX or MS-Windows too, not just the Amiga.

  The simplest way would be to open "/dev/tty" - this pseudo device is
  always pointing to the controling tty of a process.

  Unix/Linux/BSD supports pty/ttyp pairs to implement virtual lines
  for xterms and other toys. The idea behind that is, that one process
  can read/write into one side of the pair, and the other process would
  have the other side. This is used for xterm, at example.

  So clisp would just need to open a pty, and start minicom or cu
  on the other end of the ttyp pair.

Bye Michael
-- 
  mailto:[email-masked]             UNA:+.? 'CED+2+:::Linux:2.4.18'UNZ+1'
  http://www.xml-edifact.org/           CETERUM CENSEO WINDOWS ESSE DELENDAM

---

From: Sam Steingold <[email-masked]>
Date: Wed Apr 16 14:03:08 2003

> * In message <[email-masked]>
> * On the subject of "RFE: debugging in separate window"
> * Sent on Fri, 11 Apr 2003 14:02:18 +0200
> * Honorable "Hoehle, Joerg-Cyril" <[email-masked]> writes:
>
> To have *DEBUG-IO* and *ERROR-OUTPUT* point to separate console
> windows (thus keeping your standard console window clean from
> error messages) you can use: 
>        (SETQ *ERROR-OUTPUT*
>          (SETQ *DEBUG-IO*

(defun make-query-io ()
  (let ((tty-name "foo") (guard "bar"))
    (with-open-file (s guard :direction :output :if-exists :overwrite
                       :if-does-not-exist :create))
    (shell (format nil "xterm -e 'tty > ~a; read < ~a' &" tty-name guard))
    (sleep 1)
    (setq tty-name
          (prog1 (with-open-file (s tty-name :direction :input)
                   (read-line s))
            (delete-file tty-name)))
    (make-two-way-stream
     (open tty-name :direction :input)
     (open tty-name :direction :output))))

this does not work because I do not know how to implement the `guard':
I want the guard to prevent the xterm from exiting.

there is no mktemp() in CL, right?

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
A computer scientist is someone who fixes things that aren't broken.

---

From: Sam Steingold <[email-masked]>
Date: Thu Apr 17 17:05:10 2003

>            (OPEN "CON:0/0/500/300/CLISP-Debugger/AUTO/CLOSE"

UNIX:

(defun make-xterm-io ()
  (let* ((pipe (read-line (make-pipe-input-stream "mktemp fooXXXXXX")))
         tty-name xio)
    (shell (format nil "rm -f ~a; mknod ~a p; xterm -e 'tty >> ~a; cat ~a' &"
                   pipe pipe pipe pipe))
    (setq tty-name
          (with-open-file (s pipe :direction :input) (read-line s))
          xio (make-two-way-stream
               (open tty-name :direction :input)
               (open tty-name :direction :output)))
    (finalize xio (lambda (junk)
                    (declare (ignore junk))
                    (with-open-file (s pipe :direction :output)
                      (format s "goodbye!~%"))
                    (delete-file pipe)))
    xio))

(SETQ *ERROR-OUTPUT*
      (SETQ *DEBUG-IO* (make-xterm-io)))

the xterm will go when the stream is GCed, which will happen at a
non-deterministic time.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
We're too busy mopping the floor to turn off the faucet.

---

From: Sam Steingold <[email-masked]>
Date: Fri Apr 18 06:33:28 2003

Here is the final version:

(defun make-xterm-io ()
  (let* ((pipe (with-open-stream (s (make-pipe-input-stream
                                     "mktemp /tmp/clisp-x-io-XXXXXX"))
                 (read-line s)))
         (title "CLISP query IO")
         tty-name xio
         (clos::*warn-if-gf-already-called* nil))
    (shell (format nil "rm -f ~a; mknod ~a p; ~
                   xterm -n ~s -T ~s -e 'tty >> ~a; cat ~a' &"
                   pipe pipe title title pipe pipe))
    (setq tty-name
          (with-open-file (s pipe :direction :input) (read-line s))
          xio (make-two-way-stream
               (open tty-name :direction :input)
               (open tty-name :direction :output)))
    (defmethod close :after ((x (eql xio)) &rest junk)
      (declare (ignore x junk))
      (with-open-file (s pipe :direction :output)
        (format s "goodbye!~%"))
      (delete-file pipe)
      (close (two-way-stream-input-stream xio))
      (close (two-way-stream-output-stream xio))
      (let ((clos::*warn-if-gf-already-called* nil))
        (remove-method #'close (find-method #'close '(:after) `((eql ,xio))))))
    xio))

(with-open-stream (*query-io* (make-xterm-io)) (y-or-n-p "foo?"))

please try it.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
cogito cogito ergo cogito sum