         (when (empty? @name-endpoint-map)
           (Thread/sleep 100)
           (when (= 20 count)
-            (println "\nSearching for devices ..."))
+            ((:print opts) "\nSearching for devices ..."))
           (recur (inc count))))
       (Thread/sleep 500)                                    ;; Sleep a little more to catch stragglers
       (loop [current-name-endpoint-map @name-endpoint-map]
-        (println)
-        (print-discovered-devices current-name-endpoint-map)
+        ((:print opts))
+        (print-discovered-devices current-name-endpoint-map opts)
         (when-not choose-first-discovered?
-          (println "\n[R] Refresh\n")
-          (print "Choice: ")
-          (flush))
+          ((:print opts) "\n[R] Refresh\n")
+          ((:print-no-newline opts) "Choice: ")
+          ((:flush opts)))
         (let [choice (if choose-first-discovered? "1" (read-line))]
           (if (= "r" (.toLowerCase choice))
             (recur @name-endpoint-map)

        _ (.mkdirs output-dir)
        env (ana/empty-env)
        core (io/resource "cljs/core.cljs")]
    (println "\nConnecting to" (bonjour-name->display-name bonjour-name) "...\n")
    (reset! (:webdav-mount-point repl-env) webdav-mount-point)
    (shell/sh "mount_webdav" (str "http://" endpoint-address ":" endpoint-port) webdav-mount-point)
    (reset! (:socket repl-env)
      (socket endpoint-address (:port repl-env)))
    ;; Start dedicated thread to read messages from socket
    (start-reading-messages repl-env)
    ;; compile cljs.core & its dependencies, goog/base.js must be available
    ;; for bootstrap to load, use new closure/compile as it can handle
    ;; resources in JARs

                   (deliver resp-promise :eof))
                 :eof)
      (= c 1) (do
                ((:print-no-newline opts) (str sb))
                ((:flush opts))
                (recur (StringBuilder.) (.read in)))
      (= c 0) (do
                (deliver @response-promise (str sb))
