CLIM mail archive

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

Command parser problem



First a simple thing...  It appears that an interactor pane is not a valid
argument to STREAM-FINISH-OUTPUT but it is ok for your other STREAM- functions.

Now a moderate problem:  In Gnuemacs with Allegro running under it, I
get an error when I try to compile the DEFINE-PRESENTATION-TYPE SENTENCE
below by itself (ie, in a file buffer) but Allegro compiles it fine when
it compiles the file it is in.  I don't know if that is some problem
related to CLIM, but ...


Now the complex thing...  The code below purports to read a sentence from
the stream.  If MULTILINE is true, then it reads until it sees two blank
lines.  Try calling it with
#+Symbolics         (accept '((clim-demo::sentence) :multiline nil))
#-Symbolics         (accept '(clim-demo::sentence :multiline nil))
and then the same thing with :MULTILINE T  (where the stream is an interactor
in an application).

At least in Franz lisp, CLIM 1 0.9, the :MULTILINE T version goes into an
infinite loop as it tries to update the cursor position from the input
(as it rescans the input after I have added a \newline to it).

Basically all I want to do is to have the return that the user types be
echoed somehow (and be seen by the parser for the sentence).  I tried various
other approaches and couldn't get it to work.  Any hints, or is this
contradictory to the design, or is it a bug?


[Also, am I wrong or can I avoid the two different forms of the call to
ACCEPT above and the two different arglists for SENTENCE in the 
DEFINE-PRESENTATION-TYPE below.]



#+Symbolics  ;Ignore while in CLIM-DEMO package under CLIM
(defmacro with-input-editing ((stream) &body body)
  #+Symbolics `(scl:with-input-editing (,stream) ,@body)
  #-Symbolics `(clim:with-input-editing (,stream) ,@body))

(defun replace-whole-input (stream string &key rescan)
  #+Symbolics (send-if-handles stream :replace-input nil string 0 nil (if rescan :enable :ignore))
  #-Symbolics (clim:replace-input stream string :buffer-start 0 :rescan rescan))

(defmacro read-char-for-accept (stream)
  #+Symbolics `(dw:read-char-for-accept ,stream)
  #-Symbolics `(clim:stream-read-char ,stream))

(defmacro unread-char-for-accept (char stream)
  #+Symbolics `(dw:unread-char-for-accept ,char ,stream)
  #-Symbolics `(clim:stream-unread-char ,char ,stream))

(defun compare-char-for-accept (c1 c2)
  #+Symbolics (dw:compare-char-for-accept c1 c2)
  #-Symbolics (char-equal c1 c2))

(defconstant *return-char-word* (format nil "~%"))

;;; The semantic intent is for this to read a sentence from the stream
;;; If MULTILINE is nil, then it reads until the first return and generates a string of the input
;;;   (On Symbolics, it may put a "." at the end of the input line.)
;;; If MULTILINE is T, then it reads until it gets an empty line (ie, two consecutive returns).
;;; In that case, the value is the string of all input up until that point (including returns).
(defun READ-A-SENTENCE (stream &optional multiline)
  (flet ((add-a-return (sentence-so-far)
	   (replace-whole-input stream (apply 'concatenate 'string (reverse sentence-so-far)) :rescan t))
	 )
    (with-input-editing (stream)
      (let () ;; Temporarily remove this for testing purposes... ((*readtable* diamond-readtable))
	(loop named sentence
	      with sentence = nil
	      for line = (make-array 120. :element-type 'character :fill-pointer 0)
	      do (loop for char = (read-char-for-accept stream)
		       do
		   (cond ((compare-char-for-accept char #\return)
			  (when (not (string-equal (string-trim '(#\space #\tab) (coerce line 'string)) "")) ;Franz complained that line was not a string
			    (push line sentence))
			  (cond ((null sentence)	;(;(add-a-return sentence) (return nil))	;An empty sentence is not acceptable
				 (return-from sentence (values nil :empty-line)))	;I believe this is used in the Command Processor stuff (for rubout of whole sentence)
				((not multiline)	;Non multiline sentences end here.
				 (when (and t	;nil	;Jerry doesn't want periods on the end of his sentences!
					  (not (char-equal
						 (char (coerce (first sentence) 'string)
						       (1- (length (first sentence))))
						 #\.)))
				     (progn
				       (setf (first sentence)
					     (concatenate 'string (first sentence) "."))
				       (add-a-return sentence))
				     (add-a-return sentence))
				 (return-from sentence (apply #'concatenate 'string (nreverse sentence))))
				((equal (first sentence) *return-char-word*)	;Multiline sentences are ended by a blank line
				 (add-a-return sentence)
				 (return-from sentence (apply 'concatenate 'string (nreverse sentence))))
				(t (push *return-char-word* sentence)	;Multiline sentences need to know where line terminations are
				   (add-a-return sentence)	;A return in the middle of a sentence
				   (return nil))))		;That line was finished
			 ((characterp char) 
			  (when (and (null sentence)	;It is the first word
				     (eql (length line) 0))	;and the first character
			    (when (and (null sentence)
				       (member char '(#\: #\, #\() :test #'char-equal ))	;For Symbolics Command processor
			      (unread-char-for-accept char stream)
			      (return-from sentence (values nil :reparse)))	;Just to prevent people from getting the wrong thing here....
			    (replace-whole-input stream (string (setq char (char-upcase char)))
						 :rescan nil)
			    )
			  (vector-push-extend char line)))))))))

#+Symbolics
(scl:define-presentation-type SENTENCE (()
					&key multiline)
   :no-deftype nil				;We will have a type of a sentence
   :history t					; and we will keep our own history
   :description "sentence"
   :printer
   ((sentence stream)
    (if scl:*print-readably*
	(format stream "~S" sentence)
	(format stream "~A" sentence)))
   :parser ((stream)
	    (read-a-sentence stream multiline))
   )
#-Symbolics
(clim:define-presentation-type sentence (&key multiline)
   :printer
   ((sentence stream &key acceptably)
    (if acceptably
	(cerror nil "Print the sentence anyway" "Can't print a sentence acceptably")
	(format stream "~A" sentence)))
   :parser ((stream &key default)
	    (declare (ignore default))
	    (read-a-sentence stream multiline))
   )

0, answered, forwarded,,

Follow-Ups:

Main Index | Thread Index