mirror of
https://gitlab.com/eql/EQL5.git
synced 2025-12-06 18:40:50 -08:00
59 lines
1.6 KiB
Common Lisp
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))
|