Qt Jambi and the REPL, Episode II: Hacking SLIME for Fun and Profit

49 views
Skip to first unread message

Matthias Benkard

unread,
Mar 9, 2009, 6:41:29 PM3/9/09
to Clojure
After reading a bit of stuff here and there about Swing and Qt Jambi,
I've recently started tinkering with the latter. Unfortunately, I
pretty quickly grew frustrated with the need to call out to
QCoreApplication/invokeAndWait every single time I wanted to change a
part of the GUI from the REPL or by hitting C-M-x.

Now, one of the things that make programming in Lisp so much fun is
the kind of interactivity you get from environments like SLIME.
Having this interactivity hampered by a GUI toolkit not designed to be
used interactively is a real show stopper for me. I'd rather use a
mediocre API in an interactive fashion than a superb one using a more
Javaesque development style. (Make no mistake, I don't have an
opinion about whether Qt's API is actually significantly better than
Swing's. I'm just trying to say that even if that were the case, I'd
still be using Swing.)

So... What to do? Given that we're talking Lisp here, anyway, the
solution seemed to be obvious: Hack SLIME! So that's what I did. The
code below, when dropped into your .emacs (at a point at which SLIME
is already fully loaded), registers three new Emacs-Lisp functions for
interactive use. You can bind them to whatever keys you like, or you
may even just set the slime-send-through-qapplication variable to t
after your application has started and not worry about key bindings at
all. Either should make your REPL submissions and C-M-x-style
interactive evaluations indirect through QCoreApplication/
invokeAndWait.

Have fun!


---- Code follows ----

(defvar slime-send-through-qapplication nil)
(defvar slime-repl-send-string-fn (symbol-function 'slime-repl-send-
string))
(defvar slime-interactive-eval-fn (symbol-function 'slime-interactive-
eval))

(defun qt-appify-form (form)
(concatenate 'string
"(let [return-ref (ref nil)] "
" (com.trolltech.qt.core.QCoreApplication/
invokeAndWait "
" (fn [] "
" (let [return-value (do "
form
" )] "
" (dosync (ref-set return-ref return-value))))) "
" (deref return-ref))"))

(defun slime-interactive-eval (string)
(let ((string (if slime-send-through-qapplication
(qt-appify-form string)
string)))
(funcall slime-interactive-eval-fn string)))

(defun slime-repl-send-string (string &optional command-string)
(let ((string (if slime-send-through-qapplication
(qt-appify-form string)
string)))
(funcall slime-repl-send-string-fn string command-string)))

(defun slime-eval-defun-for-qt ()
(interactive)
(let ((slime-send-through-qapplication t))
(slime-eval-defun)))

(defun slime-repl-closing-return-for-qt ()
(interactive)
(let ((slime-send-through-qapplication t))
(slime-repl-closing-return)))

(defun slime-repl-return-for-qt (&optional end-of-input)
(interactive)
(let ((slime-send-through-qapplication t))
(slime-repl-return end-of-input)))
Reply all
Reply to author
Forward
0 new messages