Saturday, January 21, 2023

Uber-REPL vs. REBL

I'm following the instructions here to create an uber-cool REPL.

Following those instructions, the ~/.lein/profiles.clj has an alias for Rebel-Readline and it's got all these other plugins and dependencies.

NOTE: I was confusing REBL with Rebel Readline. Those are two separate projects!!

However, it looks like when I execute lein rebl, I need to execute that after cd'ing into an actual project. Whereas lein repl can execute anywhere.

Also, if I do lein rebl, I don't seem to get an nREPL server and so cannot connect to it from my IDE. And there's no pprint or pst functions, whereas if I do plain old lein repl, these 2 functions are available.

I was under the impression that I could get everything with one command, the fancy Rebel Readline along with all these other goodies. But it seems like it's either-or.

Actually digging further, there looks like a way to do it:

:Rebel-Readline & Reveal

which is using the clj command line.

Since I am using leiningen, I got this to work by having this in my profiles.clj

{:user
{:dependencies [[com.bhauman/rebel-readline "0.1.4"] ;nice REPL
[vlaaad/reveal "1.3.265"]]}}

OR alternatively with an empty ~/.lein/profiles.clj, from the command line:

lein update-in :dependencies conj "[vlaaad/reveal \"1.3.265\"]" "[com.bhauman/rebel-readline \"0.1.4\"]" -- repl

and then just invoking the below lines!

user=> (require 'rebel-readline.core)
nil
user=> (require 'rebel-readline.clojure.line-reader)
nil
user=> (require 'rebel-readline.clojure.service.local)
nil
user=> (require 'vlaaad.reveal)
nil
user=> (rebel-readline.core/with-readline-in
         (rebel-readline.clojure.line-reader/create
           (rebel-readline.clojure.service.local/create))
         (vlaaad.reveal/repl :prompt (fn[])))
user=> ;; Rebel Readline starts with a Reveal window output



Friday, January 20, 2023

Misbehaving REPL

 

So I'm still studying the REPL and leiningen and Reveal and REBL and trying to get it all to work.

For the longest time, I thought the repl and lein went hand-in-hand. It was just some atomic thing you did to access Clojure. Well, lo & behold, they are actually two different things...

Lein is a tool to manage projects and dependencies and such. There are alternatives like boot and deps (I believe). Meanwhile the REPL can just be started standalone without any need to resort to lein. You can do:

java -jar clojure-1.8.0.jar

which seems like an OG way to do it.

You can also use:

clj
This makes use of the Clojure Command Line tool as can be seen in Eric Normand's guide.

So what I was aiming to do was run lein repl and invoke Reveal. I wanted to do this purely from the command line only without using any profiles.clj file. I spent a LOOOONG time trying out all kinds of commands with various switches. No dice!

Here's just a quick snapshot of things I tried. I used the VSCode Calva to assist with different commands I could use, all to no avail.

lein update-in :dependencies conj '[[vlaaad/reveal \"1.3.276\"]]' -- repl

lein update-in :dependencies conj '[[vlaaad/reveal \"1.3.276\"]]' -- repl // persistent vector cannot be cast to class Named
lein update-in :dependencies conj '[[vlaaad/reveal, \"1.3.276\"]]' -- repl // unsupported character \"1.3.276

lein update-in :dependencies conj '["[vlaaad/reveal, \"1.3.276\"]"]' -- repl // Provided artifact is missing a version

lein update-in :dependencies conj '["[vlaaad/reveal 1.3.276]"]' -- repl
lein update-in :dependencies conj '["[vlaaad/reveal \"1.3.276\"]"]' -- repl
lein update-in :dependencies conj '["vlaaad/reveal \"1.3.276\""]' -- repl

lein update-in :dependencies conj '[[vlaaad/reveal,"1.3.276"], [nrepl, "0.9.0"], [cider/piggieback, "0.5.3"], [cider/cider-nrepl, "0.28.0"]]' -- repl

lein update-in :dependencies conj '[vlaaad/reveal,"1.3.276"]' -- update-in :dependencies conj '[nrepl,"1.0.0"]' -- update-in :dependencies conj '[cider/piggieback,"0.5.3"]' -- update-in :dependencies conj '[cider/cider-nrepl,"0.28.5"]' --repl

lein update-in :dependencies conj '[vlaaad/reveal,"1.3.276"]' -- repl // opens REPL no complaints BUT require doesn't work as it cannot find source code for reveal


lein update-in :dependencies conj \[nrepl/nrepl \ \"0.9.0 \" \] -- update-in :plugins conj \[cider/cider-nrepl \ \"0.28.1 \" \] -- repl :headless :host localhost  


So I was using all these update-in commands without knowing how they work. I got the gist of what it was doing but I was using them as a magic incantation. Then somehow I stumbled onto lein help update-in; it was in the docs all along, just missed it and I saw this in the help:

$ lein update-in :dependencies conj "[slamhound \"1.1.3\"]" -- repl

So a lot easier than what I was trying to do! So I simply did:

$ lein update-in :dependencies conj "[vlaaad/reveal \"1.3.277\"]" -- repl 

and got the REPL going! Success! but that didn't last long, because when I did:

user=> (require '[vlaaad.reveal :as r])

Syntax error (ClassNotFoundException) compiling at (fipp/ednize.clj:1:1).

java/sql/Timestamp

Drats! However, after even MORE noodling around, looks like the version is causing a problem. I went back to 1.3.265 and loookeee here:



Got it to work! And ~/.lein/profiles.clj was empty.
That latest version of reveal seems to be buggy. I'll drop a note in Clojurians slack to see whatsup.


My next task will be to use profiles.cljs and create a REPL with all the goodies: Reveal, REBL, pprint, nicer stack tracing, etc.

Thursday, January 19, 2023

Reveal / REPL / VSCode Adventures

So the latest odyssey is to get Reveal working. And I'm trying to get it to run:

  • Using VSCode & Calva
  • Using Leiningen
Needless to say, my first few attempts didn't work in my guestbook project.
So back to basics.
If I put this into ~/.lein/profiles.clj

{:user {:dependencies [[vlaaad/reveal "1.3.265"]
                       [nrepl "0.9.0"]
                       [cider/piggieback "0.5.3"]
                       [cider/cider-nrepl "0.28.0"]]
        :repl-options {:nrepl-middleware [vlaaad.reveal.nrepl/middleware]}}}


and then do:

lein new app (on the command line)

followed by

lein repl (on the command line)

I get a beautiful Reveal window that when I execute a command in the REPL, I get output in the Reveal window


But if I do this within VSCode / Calva and jack-in, the Reveal window pops up

but notice I hardly get any output (as compared to the previous screenshot).

And when I execute the same command in my REPL window in VSCode, nothing appears in Reveal.

Hmmm? Stuck!


As an aside, I ran into REBL-readline and tried it out using the instructions here: https://www.futurile.net/2020/03/01/clojure-development-2020-lein-rebel-readline/

Very nice! But not sure how I can get this to play with my IDE. The IDE uses nREPL to talk to the REPL. how does REBL readline fit in here??

The author of the above REBL post goes into detail here on how to fully blow up the REPL experience with additional plugins and such. I want to follow this at some point. 

However, I want to keep my ~/.lein/profiles.clj empty at the moment as I'm trying to get the IDE working with Reveal and don't want to add anything unnecessary.


Full-Stack Development

I'm building the guestbook web application by following the book Web Development with Clojure which is a wonderful book. However, I do get thrown off now and again as I read the code. I think I get it... and I explain it to myself but I'm not certain. It could be me hand-waving things away.

So I've been reading about debugging in Clojure, namely by watching/reading the following resources:


and I thought why not apply this to the guestbook app? So I can validate what I'm reading. Is that data structure holding what I think it's holding?

Till now, I've been launching the guestbook app:
  1. Server
    1. lein repl in a terminal OR
    2. Server configuration in VS Code/Calva
  2. Shadow-CLJS
    1. npx shadow-cljs watch app in a terminal
But I wanted to be able to be do everything in VSCode! 

After scouring various docs on the Calva site, I came across the following:
https://calva.io/luminus/ which has a video on how to create an app from scratch that is full-stack and uses shadow-cljs. BINGO! I then basically (painstakingly) went through the startup configurations of this demo app vs. the guestbook app to figure out what the difference was. The demo app could launch both the Server and CLJS and be able to REPL into both. I could only REPL into the server.

Somehow I stumbled onto settings.json which is part of VS Code and BAM, I saw how the demo app had a Server + Client config which I didn't have. This included a launchBuild and a command to start the server. This is exactly what I was missing in the guestbook app. These are actually called Connect Sequences. And after I copied it over to guestbook app, I was able to launch both Server + Client in one VS Code instance!

I also came across this goody on how the REPL works: https://blog.agical.se/en/posts/shadow-cljs-clojure-cljurescript-calva-nrepl-basics/ which I need to delve into.

But I also discovered the following cool resources as well that are on my list now to explore more:

Next Steps:
  1. Following the VSCode Calva tutorial, Welcome to Clojure, there are some instructions on how to use the Clojure debugger. I tried that with a piece of CLJS code to see if it would break when I hit the webpage, but I got a weird error. It does work with Clojure code though!
  2. Try out Tap
  3. Try out Reveal

Clojurescript with Reveal & VSCode

So my next foray was into getting Reveal to work with Clojurescript ( specifically Shadow-CLJS)  and VSCode and Leiningen. After a number of...