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