forge:repl: allow list input over multiple lines, using handler-bind and restart-case in string-iterator

This commit is contained in:
Helmut Merz 2026-02-06 14:26:24 +01:00
parent 685df331b0
commit 3c3e9b15d7
2 changed files with 20 additions and 11 deletions

View file

@ -85,7 +85,11 @@
(defun repl () (defun repl ()
(do ((input (read-line) (read-line))) (do ((input (read-line) (read-line)))
((string= input "q") (stack *forge-env*)) ((string= input "q") (stack *forge-env*))
(exec-string input))) (handler-bind
((end-of-file
(lambda (c)
(invoke-restart 'iter:try-with-more-input (read-line)))))
(exec-string input))))
(defun exec-list (lst) (defun exec-list (lst)
(let ((*input* (iter:list-iterator lst))) (let ((*input* (iter:list-iterator lst)))

View file

@ -6,7 +6,8 @@
(defpackage :scopes/util/iter (defpackage :scopes/util/iter
(:use :common-lisp) (:use :common-lisp)
(:export #:stop #:next #:value #:next-value #:process (:export #:stop #:next #:value #:next-value #:process
#:list-iterator #:string-iterator #:stream-iterator)) #:list-iterator #:string-iterator #:stream-iterator
#:try-with-more-input))
(in-package :scopes/util/iter) (in-package :scopes/util/iter)
@ -56,7 +57,7 @@
;;;; string iterator implementation ;;;; string iterator implementation
(defclass string-iterator (iterator) (defclass string-iterator (iterator)
((data :reader data :initarg :data :initform "") ((data :accessor data :initarg :data :initform "")
(curpos :accessor curpos :initform 0) (curpos :accessor curpos :initform 0)
(value :accessor value :initform nil))) (value :accessor value :initform nil)))
@ -64,14 +65,18 @@
(make-instance 'string-iterator :data s)) (make-instance 'string-iterator :data s))
(defmethod next ((it string-iterator)) (defmethod next ((it string-iterator))
(let ((pos (curpos it))) (restart-case
(if (< pos (length (data it))) (let ((pos (curpos it)))
(multiple-value-bind (val newpos) (if (< pos (length (data it)))
(read-from-string (data it) nil nil :start pos) (multiple-value-bind (val newpos)
(setf (curpos it) newpos (read-from-string (data it) nil nil :start pos)
(value it) val) (setf (curpos it) newpos
nil) (value it) val)
t))) nil)
t))
(try-with-more-input (more)
(setf (data it) (str:join " " (list (data it) more)))
(next it))))
;;;; stream iterator implementation ;;;; stream iterator implementation