1 (in-package :cl-smoke.repl)
5 (defclass qt-eval (qt:object)
6 ((eval-slot :initform (qt:make-slot
8 (setf (result *qt-eval*) (multiple-value-list (eval form))
9 (new-package *qt-eval*) *package*))
12 (eval-signal :initform (qt:make-signal t)
14 :documentation "Send an form to evaluate.")
15 (result :accessor result)
16 (package :accessor new-package :initarg :package))
17 (:metaclass cxx:class))
19 (defmethod initialize-instance :after ((qt-eval qt-eval) &key &allow-other-keys)
20 (qt:connect (eval-signal qt-eval) (eval-slot qt-eval) qt:+blocking-queued-connection+))
23 "Returns the result of FORM evaluated in the event loop thread."
24 (funcall (eval-signal *qt-eval*) form)
25 (setf *package* (new-package *qt-eval*))
26 (values-list (result *qt-eval*)))
28 (let ((eval-region-orig))
29 (defun end-event-loop ()
32 (assert eval-region-orig)
33 (setf (fdefinition 'swank::eval-region)
35 (setf eval-region-orig nil))
37 (defun start-event-loop-in-background ()
38 "Starts the QApplication event loop in a new thread and
39 sends the forms entered at the REPL to this thread to be evaluated."
40 ;; Like eval-region of Slimes swank.lisp
43 (assert (null eval-region-orig))
44 (setf eval-region-orig
46 (setf (fdefinition 'swank::eval-region)
48 (with-input-from-string (stream string)
51 (let ((form (read stream nil stream)))
52 (when (eq form stream)
55 (return (values values -)))
57 (setq values (multiple-value-list (qt-eval form)))
58 (finish-output))))))))
59 (let ((standard-input *standard-input*)
60 (standard-output *standard-output*)
62 (trace-output *trace-output*)
63 (error-output *error-output*)
65 (terminal-io *terminal-io*)
66 (ready-lock (bt:make-lock))
67 (ready (bt:make-condition-variable)))
68 (bt:make-thread #'(lambda ()
70 (setf *standard-input* standard-input
71 *standard-output* standard-output
73 *trace-output* trace-output
74 *error-output* error-output
76 *terminal-io* terminal-io)
78 (qt:application.set-quit-on-last-window-closed nil)
79 (setf *qt-eval* (make-instance 'qt-eval :package *package*))
80 (qt:do-delayed-initialize
81 (bt:condition-notify ready))
82 (qt:connect (qt:get-signal (qt:app)
85 (setf *qt-eval* nil)))
87 :name "Qt Event Loop")
88 (bt:with-lock-held (ready-lock)
89 (bt:condition-wait ready ready-lock)))))
92 (defun start-event-loop-in-repl ()
93 "Start the QApplication event loop in the current REPL thread.
94 When idle the event loop updates the REPL.
96 While the idea is fine, it is a hack and the displaying of the argument list
98 (funcall swank::*send-repl-results-function* '(nil))
100 (qt:application.set-quit-on-last-window-closed nil)
101 (let ((idle (make-instance 'qt:timer)))
102 (qt:connect (qt:get-signal idle "timeout()")
104 (swank::process-requests t) ;; it's a wonder this even works!
105 (sb-impl::serve-event 0.1)))
108 (format *debug-io* "New-repl end~%"))))