[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

clim command tables



    Date: Tue, 18 Feb 1992 12:39 PST
    From: attila@merlin.bellcore.com (Leslie A. Walko)

    Is there a way of making clim command line to process application
    commands, s-expressions and possibly operating system commands?

I have included a sample application at the end of this message.  The
idea is to replace the standard command reader with one that knows how
to read and interpret different input syntaxes.

    My DW application does this by inheriting from various command
    tables such as

While CLIM does support the "command or form" mode, it doesn't have as
many heuristics as DW does.  For example, in command-or-form mode you
MUST prefix the commands with a ":" character.  Following on that theme,
my example looks for a different character ("!") to indicate that the
input is supposed to be a Unix shell command line.  That is, if the
first thing you type on a line is an ! character, the rest of the line
is read as a string and passed to the Unix shell (or, in my simple
example, simply printed).

In order to support a real Lisp-listener-like interaction you need more
hair than I have the space to include here.  See the LISTENER.LISP demo
program for more information.

    So, how do I make the new application frame command line behave
    like the old program framework command line?

Like this:


;;; -*- Mode: LISP; Syntax: Common-Lisp; Base: 10; Package: CLIM-USER -*-

;;; Simple frame with one pane.
(define-application-frame example ()
    ()
  (:panes ((the-interactor :interactor)))
  )

;;; Simple command.
(define-example-command (com-dummy :name t) ()
  (write-string "Yow!" (get-frame-pane *application-frame* 'the-interactor)))

;;; More useful command.
(define-example-command (com-quit :name t) ()
  (frame-exit *application-frame*))

;;; Replace the default READ-FRAME-COMMAND method with one that
;;; reads commands and forms and also supports an escape to
;;; the Unix shell.
(defmethod read-frame-command ((frame example) &key stream)
  (let ((char (peek-char)))			; Look ahead for the escape
    (if (eql char #\!)				; Unix escape
	(read-char)				; get rid of !
	(let ((line (read-line)))		; read Unix command line
	  (format t "~&Would execute Unix command ~S" line))
	;; Otherwise, read a command or a form.
	(multiple-value-bind (value type)
	    (accept `(command-or-form :command-table ,(frame-command-table frame))
		    :stream stream)
	  ;; If it is a form, EVAL it here.  See the LISTENER.LISP demo
	  ;; for a real example of a form-reading top level.
	  (case type
	    (form
	      ;; Should have some error handling here.
	      (print (eval value) (get-frame-pane *application-frame* 'the-interactor))
	      ;; Return NIL to go around the command-reading loop again.
	      nil)
	    ;; Assume that it is a command.
	    (otherwise
	      value))))))

(defun run-example (root)
  (let ((frame (make-application-frame 'example :parent root :width 400 :height 300)))
    (run-frame-top-level frame)))