         (when (empty? @name-endpoint-map)
           (Thread/sleep 100)
           (when (= 20 count)
-            ((println-fn opts) "\nSearching for devices ..."))
+            (repl-println 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-fn opts))
+        (repl-println opts "")
         (print-discovered-devices current-name-endpoint-map opts)
         (when-not choose-first-discovered?
-          ((println-fn opts) "\n[R] Refresh\n")
-          ((print-fn opts) "Choice: ")
-          ((flush-fn opts)))
+          (repl-println opts "\n[R] Refresh\n")
+          (repl-print opts "Choice: ")
+          (repl-flush opts))
         (let [choice (if choose-first-discovered? "1" (read-line))]
           (if (= "r" (.toLowerCase choice))
             (recur @name-endpoint-map)

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

  {:pre [(every? string? args)]}
  (.waitFor (.exec (Runtime/getRuntime) (string/join " " args))))

(defn repl-print [opts msg]
  {:pre [(map? opts)]}
  ((or (:print-no-newline opts) print) msg))

(defn repl-println [opts msg]
  {:pre [(map? opts)]}
  ((or (:print opts) println) msg))

(defn repl-flush [opts]
  {:pre [(map? opts)]}
  (or (:flush opts) flush))

