lambdaisland / trikl

Terminal UI library for Clojure

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Crash when connecting

saikyun opened this issue · comments

I'm trying to follow along the example. I start a socket repl, and eval the following lines:

(require '[trikl.core :as t])

;; store clients so we can poke at them from the REPL
(def clients (atom []))

;; Start the server on port 1357, as an accept handler just store the client in
;; the atom.
(def stop-server (t/start-server #(swap! clients conj %) 1357))

Then when connecting using telnet localhost 1357 I get the following exception in the repl window:

Exception in server loop #error {
 :cause class java.net.Socket$SocketOutputStream cannot be cast to class java.io.FileOutputStream (java.net.Socket$SocketOutputStream and java.io.FileOutputStream are in module java.base of loader 'bootstrap')
 :via
 [{:type java.lang.ClassCastException
   :message class java.net.Socket$SocketOutputStream cannot be cast to class java.io.FileOutputStream (java.net.Socket$SocketOutputStream and java.io.FileOutputStream are in module java.base of loader 'bootstrap')
   :at [trikl.telnet$send_telnet_command invokeStatic telnet.clj 31]}]
 :trace
 [[trikl.telnet$send_telnet_command invokeStatic telnet.clj 31]
  [trikl.telnet$send_telnet_command doInvoke telnet.clj 31]
  [clojure.lang.RestFn invoke RestFn.java 2442]
  [trikl.telnet$prep_telnet invokeStatic telnet.clj 39]
  [trikl.telnet$prep_telnet invoke telnet.clj 38]
  [trikl.core$start_client invokeStatic core.clj 526]
  [trikl.core$start_client invoke core.clj 524]
  [trikl.core$make_client invokeStatic core.clj 557]
  [trikl.core$make_client doInvoke core.clj 547]
  [clojure.lang.RestFn invoke RestFn.java 442]
  [trikl.core$start_server$fn__599 invoke core.clj 625]
  [clojure.core$binding_conveyor_fn$fn__5754 invoke core.clj 2030]
  [clojure.lang.AFn call AFn.java 18]
  [java.util.concurrent.FutureTask run FutureTask.java 264]
  [java.util.concurrent.ThreadPoolExecutor runWorker ThreadPoolExecutor.java 1128]
  [java.util.concurrent.ThreadPoolExecutor$Worker run ThreadPoolExecutor.java 628]
  [java.lang.Thread run Thread.java 830]]}

I'm on MacOS. Have tried connecting using eshell and shell in emacs, and zsh terminal.

Hi Saikyun,

This is an unfinished research project. It's not ready for general consumption. There's useful code in here but you'll have to dive in and piece it together yourself.

@saikyun if I may hazard a guess: check your JVM version?

FWIW, I just tried out the following (on a freshly checked out version):

  1. Set up basic listener
user=> (def stop-server (t/start-server #(swap! clients conj %) 1357))
#'user/stop-server
  1. Connect to it
    (I ran this in a different shell)
telnet localhost 1357
  1. Sanity check
user=> clients
#object[clojure.lang.Atom 0x3419e23b {:status :ready, :val [{:socket #object[java.net.Socket 0x34b27915 "Socket[addr=/127.0.0.1,port=53386,localport=1357]"], :in #object[java.net.SocketInputStream 0x29eda4f8 "java.net.SocketInputStream@29eda4f8"], :out #object[java.net.SocketOutputStream 0x1b9776f5 "java.net.SocketOutputStream@1b9776f5"], :size #object[clojure.lang.Atom 0x5e048149 {:status :ready, :val [51 185]}], :screen #object[clojure.lang.Atom 0x79d9214d {:status :ready, :val nil}], :listeners #object[clojure.lang.Atom 0x3d5790ea {:status :ready, :val {:resize #object[trikl.core$make_client$fn__564 0x1dd7796b "trikl.core$make_client$fn__564@1dd7796b"]}}], :input-loop #object[clojure.core$future_call$reify__8439 0x67a3bd51 {:status :ready, :val nil}]} {:socket #object[java.net.Socket 0x57402ba1 "Socket[addr=/127.0.0.1,port=53388,localport=1357]"], :in #object[java.net.SocketInputStream 0x56913163 "java.net.SocketInputStream@56913163"], :out #object[java.net.SocketOutputStream 0x702b06fb "java.net.SocketOutputStream@702b06fb"], :size #object[clojure.lang.Atom 0xa18649a {:status :ready, :val [51 185]}], :screen #object[clojure.lang.Atom 0x5c534b5b {:status :ready, :val nil}], :listeners #object[clojure.lang.Atom 0x396639b {:status :ready, :val {:resize #object[trikl.core$make_client$fn__564 0x2b22a1cc "trikl.core$make_client$fn__564@2b22a1cc"]}}], :input-loop #object[clojure.core$future_call$reify__8439 0x62573c86 {:status :pending, :val nil}]}]}]
  1. Show something to this client
    (this example is lifted from the README)
(t/render (last @clients) #_(t/stdio-client)
          [:box {:x 10 :y 5 :width 20 :height 10 :styles {:bg [50 50 200]}}
           [:box {:x 1 :y 1 :width 18 :height 8 :styles {:bg [200 50 0]}}
            [:box {:x 3 :y 1}
             [:span {:styles {:fg [30 30 150]}} "hello\n"]
             [:span {:styles {:fg [100 250 100]}} "  world"]]]])
  1. Verify client view
    In the shell with my telnet session, I now see a red square with a blue border and "hello world" in the middle

  2. Verify client state

user=> (type (last @clients))
clojure.lang.PersistentArrayMap
user=> (keys (type (last @clients)))
Execution error (IllegalArgumentException) at user/eval627 (REPL:1).
Don't know how to create ISeq from: java.lang.Class
user=> (keys (last @clients))
(:socket :in :out :size :screen :listeners :input-loop)
user=> (:socket (last @clients))
#object[java.net.Socket 0x57402ba1 "Socket[addr=/127.0.0.1,port=53388,localport=1357]"]
user=> (:size (last @clients))
#object[clojure.lang.Atom 0xa18649a {:status :ready, :val [51 185]}]
user=> (:listeners (last @clients))
#object[clojure.lang.Atom 0x396639b {:status :ready, :val {:resize #object[trikl.core$make_client$fn__564 0x2b22a1cc "trikl.core$make_client$fn__564@2b22a1cc"]}}]

(and attempting to show (:screen (@last clients)) will dump "all the noise", if you want to confirm the terminal screen state)

Hope that helps!