;;; This function sets up a toggleable swank listener in a Lisp ;;; program. This enables a REPL directly in the running process, ;;; providing unparalled introspection, debugging, and speed of ;;; development. It performs some initial setup, sets up a closure ;;; over a status variable, and then swaps out the setup code for the ;;; production code. (defun start-swank (&key (port 4006)) "Setup a swank server in the running process." ;;; The `swank-running-p` variable is used to keep track of the ;;; function's state: is swank running? (let ((swank-runningp nil)) ;;; We create a new, locally-scoped function. (labels ((fn () (progn (if swank-runningp (progn ;;; if swank is running, we print a message to the ;;; console alerting the programmer that swank is ;;; shutting down. (format t "Stopping swank server...~%") ;;; Then, stop swank. (swank:stop-server port) ;;; Finally, update the swank status ;;; variable. (setf swank-runningp nil)) (progn ;;; If swank is not running, let the ;;; programmer know that it is being started. (format t "Starting swank server on port ~A.~%" port) ;;; Start the server, and make sure that it ;;; doesn't close when the function exits. (swank:create-server :port port :dont-close t) ;;; Finally, update our status. (setf swank-runningp t))) ;;; After taking the appropriate action, we'll return the ;;; current swank state so that it can be programmatically ;;; acted on. swank-runningp))) ;;; Swap out the setup code for our locally defined function. (setf (symbol-function 'start-swank) #'fn) ;;; The function is called `start-swank`, so we start swank. (start-swank))))