EQL5/examples/9-simple-lisp-editor/input-hook.lisp
2016-11-25 23:30:38 +01:00

59 lines
1.6 KiB
Common Lisp

;;; idea & most code from "ecl-readline.lisp"
(defpackage input-hook
(:use :common-lisp)
(:export
#:new))
(provide :input-hook)
(in-package :input-hook)
(defvar *functions* nil)
(defun new (function)
(let ((stream (make-instance 'gray::input-hook-stream)))
(push (cons stream function) *functions*)
stream))
(in-package :gray)
(defclass input-hook-stream (fundamental-character-input-stream)
((in-buffer :initform (make-string 0))
(in-index :initform 0)
(out-buffer :initform (make-array 0 :element-type 'character :adjustable t :fill-pointer t))))
(defmethod stream-read-char ((stream input-hook-stream))
(if (ensure-stream-data stream)
(with-slots (in-buffer in-index) stream
(let ((ch (char in-buffer in-index)))
(incf in-index)
ch))
:eof))
(defmethod stream-unread-char ((stream input-hook-stream) character)
(with-slots (in-index) stream
(when (> in-index 0)
(decf in-index))))
(defmethod stream-listen ((stream input-hook-stream))
nil)
(defmethod stream-clear-input ((stream input-hook-stream))
nil)
(defmethod stream-close ((stream input-hook-stream) &key abort)
(call-next-method))
(defmethod stream-peek-char ((stream input-hook-stream))
(if (ensure-stream-data stream)
(with-slots (in-buffer in-index) stream
(char in-buffer in-index))
:eof))
(defun ensure-stream-data (stream)
(with-slots (in-buffer in-index) stream
(when (= in-index (length in-buffer))
(setf in-buffer (funcall (cdr (assoc stream input-hook::*functions*)))
in-index 0))
in-buffer))