Update of /project/mcclim/cvsroot/mcclim In directory clnet:/tmp/cvs-serv26826
Modified Files: decls.lisp input-editing-drei.lisp input-editing.lisp Log Message: Added docstrings for input-editor related stuff.
--- /project/mcclim/cvsroot/mcclim/decls.lisp 2007/08/20 14:27:14 1.47 +++ /project/mcclim/cvsroot/mcclim/decls.lisp 2008/01/19 09:38:20 1.48 @@ -528,7 +528,6 @@
(defgeneric stream-input-buffer (stream)) (defgeneric (setf stream-input-buffer) (buffer stream)) -(defgeneric stream-pointer-position (stream &key pointer)) ;; (defgeneric (setf* stream-pointer-position)) (defgeneric stream-set-input-focus (stream)) (defgeneric stream-read-gesture @@ -555,28 +554,96 @@
;;; 24.1 The Input Editor
-(defgeneric input-editor-format (stream format-string &rest args)) -(defgeneric redraw-input-buffer (stream &optional start-from)) +(defgeneric input-editor-format (stream format-string &rest args) + (:documentation "This function is like `format', except that it +is intended to be called on input editing streams. It arranges to +insert "noise strings" in the input editor's input +buffer. Programmers can use this to display in-line prompts in +`accept' methods. + +If `stream' is a stream that is not an input editing stream, then +`input-editor-format' is equivalent to format.")) + + +(defgeneric redraw-input-buffer (stream &optional start-from) + (:documentation "Displays the input editor's buffer starting at +the position `start-position' on the interactive stream that is +encapsulated by the input editing stream `stream'."))
;;; 24.1.1 The Input Editing Stream Protocol
-(defgeneric stream-insertion-pointer (stream)) -(defgeneric (setf stream-insertion-pointer) (pointer stream)) -(defgeneric stream-scan-pointer (stream)) -(defgeneric (setf stream-scan-pointer) (pointer stream)) -(defgeneric stream-rescanning-p (stream)) -(defgeneric reset-scan-pointer (stream &optional scan-pointer)) -(defgeneric immediate-rescan (stream)) -(defgeneric queue-rescan (stream)) -(defgeneric rescan-if-necessary (stream &optional inhibit-activation)) -(defgeneric erase-input-buffer (stream &optional start-position)) +(defgeneric stream-insertion-pointer (stream) + (:documentation "Returns an integer corresponding to the +current input position in the input editing stream `stream's +buffer, that is, the point in the buffer at which the next user +input gesture will be inserted. The insertion pointer will always +be less than (fill-pointer (stream-input-buffer stream)). The +insertion pointer can also be thought of as an editing cursor.")) + +(defgeneric (setf stream-insertion-pointer) (pointer stream) + (:documentation "Changes the input position of the input +editing stream `stream' to `pointer'. `Pointer' is an integer, +and must be less than (fill-pointer (stream-input-buffer stream))")) + +(defgeneric stream-scan-pointer (stream) + (:documentation "Returns an integer corresponding to the +current scan pointer in the input editing stream `stream's +buffer, that is, the point in the buffer at which calls to +`accept' have stopped parsing input. The scan pointer will always +be less than or equal to (stream-insertion-pointer stream).")) + +(defgeneric (setf stream-scan-pointer) (pointer stream) + (:documentation "Changes the scan pointer of the input editing +stream `stream' to `pointer'. `Pointer' is an integer, and must +be less than or equal to (stream-insertion-pointer stream)")) + +(defgeneric stream-rescanning-p (stream) + (:documentation "Returns the state of the input editing stream +`stream's "rescan in progress" flag, which is true if stream is +performing a rescan operation, otherwise it is false. All +extended input streams must implement a method for this, but +non-input editing streams will always returns false.")) + +(defgeneric reset-scan-pointer (stream &optional scan-pointer) + (:documentation "Sets the input editing stream stream's scan +pointer to `scan-pointer', and sets the state of +`stream-rescanning-p' to true.")) + +(defgeneric immediate-rescan (stream) + (:documentation "Invokes a rescan operation immediately by +"throwing" out to the most recent invocation of +`with-input-editing'.")) + +(defgeneric queue-rescan (stream) + (:documentation "Indicates that a rescan operation on the input +editing stream `stream' should take place after the next +non-input editing gesture is read by setting the "rescan +queued" flag to true. ")) + +(defgeneric rescan-if-necessary (stream &optional inhibit-activation) + (:documentation "Invokes a rescan operation on the input +editing stream `stream' if `queue-rescan' was called on the same +stream and no intervening rescan operation has taken +place. Resets the state of the "rescan queued" flag to false. + +If `inhibit-activation' is false, the input line will not be +activated even if there is an activation character in it.")) + +(defgeneric erase-input-buffer (stream &optional start-position) + (:documentation "Erases the part of the display that +corresponds to the input editor's buffer starting at the position +`start-position'."))
;;; McCLIM relies on a text editor class (by default ;;; DREI-INPUT-EDITING-MIXIN) to perform the user interaction and ;;; display for input editing. Also, that class must update the stream ;;; buffer and the insertion pointer, cause rescans to happen, and ;;; handle activation gestures. -(defgeneric stream-process-gesture (stream gesture type)) +(defgeneric stream-process-gesture (stream gesture type) + (:documentation "If gesture is an input editing command, +stream-process-gesture performs the input editing operation on +the input editing stream `stream' and returns NIL. Otherwise, it +returns the two values gesture and type."))
;;; 24.4 Reading and Writing of Tokens
--- /project/mcclim/cvsroot/mcclim/input-editing-drei.lisp 2008/01/16 09:03:27 1.5 +++ /project/mcclim/cvsroot/mcclim/input-editing-drei.lisp 2008/01/19 09:38:20 1.6 @@ -43,7 +43,12 @@ input-editing-stream standard-encapsulating-stream) ((scan-pointer :accessor stream-scan-pointer :initform 0) - (rescan-queued :accessor rescan-queued :initform nil))) + (rescan-queued :accessor rescan-queued :initform nil)) + (:documentation "The instantiable class that implements CLIM's +standard input editor. This is the class of stream created by +calling `with-input-editing'. + +Members of this class are mutable."))
(defmethod stream-accept ((stream standard-input-editing-stream) type &rest args --- /project/mcclim/cvsroot/mcclim/input-editing.lisp 2007/08/20 14:27:14 1.56 +++ /project/mcclim/cvsroot/mcclim/input-editing.lisp 2008/01/19 09:38:20 1.57 @@ -31,10 +31,22 @@ "I true, use the Goatee editing component instead of Drei. The Goatee component is faster and more mature than Drei.")
-(defvar *activation-gestures* nil) -(defvar *standard-activation-gestures* '(:newline :return)) - -(defvar *delimiter-gestures* nil) +(defvar *activation-gestures* nil + "The set of currently active activation gestures. The global +value of this must be NIL. The exact format of +`*activation-gestures*' is unspecified. `*activation-gestures*' +and the elements in it may have dynamic extent.") + +(defvar *standard-activation-gestures* '(:newline :return) + "The default set of activation gestures. The exact set of +standard activation is unspecified, but must include the gesture +that corresponds to the #\Newline character. ") + +(defvar *delimiter-gestures* nil + "The set of currently active delimiter gestures. The global +value of this must be NIL. The exact format of +`*delimiter-gestures*' is unspecified. `*delimiter-gestures*' and +the elements in it may have dynamic extent.")
;;; These helper functions take the arguments of ACCEPT so that they ;;; can be used directly by ACCEPT. @@ -63,6 +75,19 @@ (t existing-delimiter-gestures)))
(defmacro with-activation-gestures ((gestures &key override) &body body) + "Specifies a list of gestures that terminate input during the +execution of `body'. `Body' may have zero or more declarations as +its first forms. `Gestures' must be either a single gesture name +or a form that evaluates to a list of gesture names. + +If the boolean `override' is true, then `gestures' will override +the current activation gestures. If it is false (the default), +then gestures will be added to the existing set of activation +gestures. `with-activation-gestures' must bind +`*activation-gestures*' to the new set of activation gestures. + +See also the `:activation-gestures' and +`:additional-activation-gestures' options to `accept'." ;; XXX Guess this implies that gestures need to be defined at ;; compile time. Sigh. We permit both CLIM 2.0-style gesture names ;; and CLIM 2.2 style characters. @@ -83,6 +108,21 @@ ,@body)))
(defmacro with-delimiter-gestures ((gestures &key override) &body body) + "Specifies a list of gestures that terminate an individual +token, but not the entire input, during the execution of +`body'. `Body' may have zero or more declarations as its first +forms. `Gestures' must be either a single gesture name or a form +that evaluates to a list of gesture names. + +If the boolean `override' is true, then `gestures' will override +the current delimiter gestures. If it is false (the default), +then gestures will be added to the existing set of delimiter +gestures. `With-delimiter-gestures' must bind +`*delimiter-gestures*' to the new set of delimiter +gestures. + +See also the `:delimiter-gestures' and +`:additional-delimiter-gestures' options to `accept'." ;; XXX Guess this implies that gestures need to be defined at ;; compile time. Sigh. We permit both CLIM 2.0-style gesture names ;; and CLIM 2.2 style characters. @@ -103,12 +143,16 @@ ,@body)))
(defun activation-gesture-p (gesture) + "Returns true if the gesture object `gesture' is an activation +gesture, otherwise returns false." (loop for gesture-name in *activation-gestures* when (gesture-matches-spec-p gesture gesture-name) do (return t) finally (return nil)))
(defun delimiter-gesture-p (gesture) + "Returns true if the gesture object `gesture' is a delimiter +gesture, otherwise returns false." (loop for gesture-name in *delimiter-gestures* when (gesture-matches-spec-p gesture gesture-name) do (return t) @@ -119,6 +163,32 @@ &key input-sensitizer (initial-contents "") (class ''standard-input-editing-stream class-provided-p)) &body body) + "Establishes a context in which the user can edit the input +typed in on the interactive stream `stream'. `Body' is then +executed in this context, and the values returned by `body' are +returned as the values of `with-input-editing'. `Body' may have +zero or more declarations as its first forms. + +The stream argument is not evaluated, and must be a symbol that +is bound to an input stream. If stream is T (the default), +`*standard-input*' is used. If stream is a stream that is not an +interactive stream, then `with-input-editing' is equivalent to +progn. + +`input-sensitizer', if supplied, is a function of two arguments, +a stream and a continuation function; the function has dynamic +extent. The continuation, supplied by CLIM, is responsible for +displaying output corresponding to the user's input on the +stream. The input-sensitizer function will typically call +`with-output-as-presentation' in order to make the output +produced by the continuation sensitive. + +If `initial-contents' is supplied, it must be either a string or +a list of two elements, an object and a presentation type. If it +is a string, the string will be inserted into the input buffer +using `replace-input'. If it is a list, the printed +representation of the object will be inserted into the input +buffer using `presentation-replace-input'." (setq stream (stream-designator-symbol stream '*standard-input*)) (with-keywords-removed (args (:input-sensitizer :initial-contents :class)) `(invoke-with-input-editing ,stream @@ -184,6 +254,21 @@ (pointer-button-press-handler *pointer-button-press-handler*) click-only) + "Reads characters from the interactive stream `stream' until it +encounters a delimiter or activation gesture, or a pointer +gesture. Returns the accumulated string that was delimited by the +delimiter or activation gesture, leaving the delimiter +unread. + +If the first character of typed input is a quotation mark (#"), +then `read-token' will ignore delimiter gestures until another +quotation mark is seen. When the closing quotation mark is seen, +`read-token' will proceed as above. + +`Click-only' is ignored for now. + +`Input-wait-handler' and `pointer-button-press-handler' are as +for 34stream-read-gesture" (declare (ignore click-only)) ;XXX For now (let ((result (make-array 1 :adjustable t @@ -222,6 +307,15 @@ (return (subseq result 0))))))
(defun write-token (token stream &key acceptably) + "This function is the opposite of `read-token' given the string +token, it writes it to the interactive stream stream. If +`acceptably' is true and there are any characters in the token +that are delimiter gestures (see the macro +`with-delimiter-gestures'), then `write-token' will surround the +token with quotation marks (#"). + +Typically, `present' methods will use `write-token' instead of +`write-string'." (let ((put-in-quotes (and acceptably (some #'delimiter-gesture-p token)))) (when put-in-quotes (write-char #" stream)) @@ -232,9 +326,18 @@ ;;; Signalling Errors Inside present (sic)
(define-condition simple-parse-error (simple-condition parse-error) - ()) + () + (:documentation "The error that is signalled by +`simple-parse-error'. This is a subclass of `parse-error'. + +This condition handles two initargs, `:format-string' and +`:format-arguments', which are used to specify a control string +and arguments for a call to `format'."))
(defun simple-parse-error (format-string &rest format-args) + "Signals a `simple-parse-error' error while parsing an input +token. Does not return. `Format-string' and `format-args' are as +for format." (error 'simple-parse-error :format-control format-string :format-arguments format-args))
@@ -244,20 +347,50 @@ (:report (lambda (condition stream) (format stream "Input ~S is not of required type ~S" (not-required-type-string condition) - (not-required-type-type condition))))) + (not-required-type-type condition)))) + (:documentation "The error that is signalled by +`input-not-of-required-type'. This is a subclass of +`parse-error'. + +This condition handles two initargs, `:string' and `:type', which +specify a string to be used in an error message and the expected +presentation type."))
(defun input-not-of-required-type (object type) + "Reports that input does not satisfy the specified type by +signalling an `input-not-of-required-type' error. `Object' is a +parsed object or an unparsed token (a string). `Type' is a +presentation type specifier. Does not return." (error 'input-not-of-required-type :string object :type type))
;;; 24.5 Completion
-(defvar *completion-gestures* '(:complete)) -(defvar *help-gestures* '(:help)) -(defvar *possibilities-gestures* '(:possibilities)) +(defvar *completion-gestures* '(:complete) + "A list of the gesture names that cause `complete-input' to +complete the user's input as fully as possible. The exact global +contents of this list is unspecified, but must include the +`:complete' gesture name.") + +(defvar *help-gestures* '(:help) + "A list of the gesture names that cause `accept' and +`complete-input' to display a (possibly input context-sensitive) +help message, and for some presentation types a list of +possibilities as well. The exact global contents of this list is +unspecified, but must include the `:help' gesture name.") + +(defvar *possibilities-gestures* '(:possibilities) + "A list of the gesture names that cause `complete-input' to +display a (possibly input context-sensitive) help message and a +list of possibilities. The exact global contents of this list is +unspecified, but must include the `:possibilities' gesture +name.")
(define-condition simple-completion-error (simple-parse-error) ((input-so-far :reader completion-error-input-so-far - :initarg :input-so-far))) + :initarg :input-so-far)) + (:documentation "The error that is signalled by +`complete-input' when no completion is found. This is a subclass +of `simple-parse-error'."))
;;; wrapper around event-matches-gesture-name-p to match against characters too.
@@ -584,11 +717,34 @@ :predicate predicate)))
(defun suggest (completion object) + "Specifies one possibility for +`completing-from-suggestions'. `Completion' is a string, the +printed representation of object. `Object' is the internal +representation. + +Calling this function outside of the body of +`completing-from-suggestions' is an error." (declare (ignore completion object)) (error "SUGGEST called outside of lexical scope of COMPLETING-FROM-SUGGESTIONS" ))
(defmacro completing-from-suggestions ((stream &rest args) &body body) + "Reads input from the input editing stream `stream', completing +over a set of possibilities generated by calls to `suggest' +within `body'. `Body' may have zero or more declarations as its +first forms. + +`Completing-from-suggestions' returns three values, `object', +`success', and `string'. + +The stream argument is not evaluated, and must be a symbol that +is bound to a stream. If `stream' t is (the default), +`*standard-input*' is used. `Partial-completers', +`allow-any-input', and `possibility-printer' are as for +`complete-input'. + +Implementations will probably use `complete-from-generator' to +implement this." (when (eq stream t) (setq stream '*standard-input*)) (let ((generator (gensym "GENERATOR"))