Fork me on GitHub
#babashka
<
2023-03-03
>
Steffen Glückselig09:03:24

Hi! Since recently it was possible to initalize a def and displaying its value with

(clojure.pprint/pprint (def result (#{1 2 3} 4)))
That's no longer the case - I used it a lot in my REPL, employing a REPL-command in Cursive (with clojure-extras). How could I get that functionality back?

Steffen Glückselig09:03:13

I forgot - no it just prints the var's name: #'user/result

borkdude09:03:31

this has always been the case, hasn't it?

borkdude09:03:22

either way, it's the behavior of JVM Clojure as well:

$ clj
Clojure 1.11.0
user=> (require 'clojure.pprint)
nil
user=> (clojure.pprint/pprint (def x 10))
#'user/x

Steffen Glückselig09:03:37

Thanks - I was quite sure that changed. Then something changed on my part.

borkdude09:03:17

ah yes, before that, it printed: #<Var@49e8f42e: 10>

👍 2
borkdude09:03:37

but some tools rely on what clojure JVM does, so it was changed

borkdude09:03:33

I guess you could make your own "spy" function for vars:

(defn spy [x]
  (clojure.pprint/pprint (if (var? x) @x x)))

(spy (def x 10))

🙏 2
borkdude09:03:07

or this hack:

user=> (defmethod pp/simple-dispatch clojure.lang.Var [v] (print "#var[") (print @v) (print "]"))
#object[clojure.lang.MultiFn 0x2ce45a7b "clojure.lang.MultiFn@2ce45a7b"]
user=> (clojure.pprint/pprint (def x 10))
#var[10]

borkdude09:03:16

but I don't recommend putting that into a library, just for development

grav10:03:06

If I have a script, foo.clj:

(ns foo)
(defn bar [_] (println 42))
What's the shortest path to executing bar via babashka?

grav10:03:56

I would have expected

bb foo.clj -x foo/bar
to work, but that does nothing (exit code 0). It seems I need a bb.edn which contains {:paths ["."]}, and then I can run
bb -x foo/bar

grav10:03:34

I know I can just do

(ns foo)
(defn bar [_] (println 42))
(bar)
and then simply run bb foo.clj but that doesn't play well with my workflow, when I'm eg editing foo.clj and evaluating the whole file in the repl (Conjure), since bar will then run.

grav10:03:36

Just wondering if bb foo.clj -x foo/bar could be made to work as I expected, since it would lower the bar a bit for quick bash-replacement scripts.

Steffen Glückselig10:03:34

does bb -m foo/bar the trick?

borkdude10:03:48

you need to add foo to the classpath, and then bb -x foo/bar

borkdude10:03:22

bb --classpath . -x foo/bar

❤️ 2
borkdude10:03:28

you can also just do the top level side effecty thing with:

(when (= *file* (System/getProperty "babashka.file"))
  (bar ...))

💡 2
grav10:03:28

Ah, makes sense 👍 So as soon as we're dealing with namespaces and such, I'll need to think in classpaths. I guess that makes sense

grav10:03:54

> top level side effecty thing Oh, that's a nice trick. Like python's if main__ or however it looks

borkdude10:03:11

and to install scripts that look more like projects (with multiple namespaces) use #C0400TZENE7 to install them as system-global scripts

borkdude10:03:38

for project-local tasks, use babashka tasks: https://book.babashka.org/#tasks

pesterhazy11:03:03

Any guidance on how to print better stacktraces in bb with cognitect-test-runner - or any other runner? Currently I'm getting long unhelpful sci stackframes. I was able to hack cognitext-test-runner like so:

pesterhazy11:03:07

(let [original-report clojure.test/report]
        (with-redefs [clojure.test/report
                      (fn [event]
                        (if (and (= :error (:type event))
                                 (instance? Throwable (:actual event)))
                          (do
                            (println (:cause (Throwable->map (:actual event))))
                            (->> (:actual event)
                                 (sci/stacktrace)
                                 (sci/format-stacktrace)
                                 (run! println)))
                          (original-report event)))]
          (apply test/run-tests (filter contains-tests? nses))))

pesterhazy11:03:40

which gives me

Running tests in #{"test"}

Testing bblib.slack-test
Assert failed: false
bblib.slack/post            - /Users/user/pitch/pitch-app/projects/bblib/src/bblib/slack.clj:5:1
bblib.slack-test            - /Users/user/pitch/pitch-app/projects/bblib/test/bblib/slack_test.clj:15:7
clojure.core/with-redefs-fn - <built-in>
bblib.slack-test            - /Users/user/pitch/pitch-app/projects/bblib/test/bblib/slack_test.clj:14:5

Ran 1 tests containing 0 assertions.
0 failures, 0 errors.

pesterhazy11:03:07

Any more elegant ideas about how to do this?

borkdude11:03:48

I would say that is currently the most important thing to improve, but I think what you did there is how I'd solve it too in the short term

👍 2
pesterhazy12:03:10

At the moment I have a vendored copy of cognitect-test-runner for this. If you can think of a way how I can share this better with other folks who might be looking for this, I'm curious

borkdude12:03:19

publish it as a library?

borkdude12:03:00

if the cognitect test runner is using clojure.stacktrace - perhaps we can tweak bb's builtin clojure.stacktrace to do what you're doing in the patch. this was something I wanted to try, but haven't yet

pesterhazy13:03:02

cognitect-test-runner is literally just 130 lines of wrapper for selecting individual tests from the CLI: https://github.com/cognitect-labs/test-runner/blob/master/src/cognitect/test_runner.clj

pesterhazy13:03:52

It doesn't have any code for printing stacktraces, so it just does what clojure.test does - which does indeed involve clojure.stacktrace https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L384-L395

borkdude13:03:18

feel like we have the same conversation ;)

pesterhazy13:03:20

If I read that correctly, you could also rebind stack/print-cause-trace to customize printing

borkdude13:03:55

hmm, maybe but not sure if that's possible since those pre-compiled function won't see the SCI var re-binding

pesterhazy13:03:21

Yeah, I brought it up again because this time I made some minor progress towards getting better output

🎉 2
borkdude13:03:56

I think just improving the built-in clojure.test is the best approach

pesterhazy13:03:10

Yeah that seems sensible

borkdude13:03:12

and possible also the stack/print-cause-trace

pesterhazy13:03:31

Out of curiosity, how would you patch clojure.test - do you bundle your own copy of the file?

borkdude13:03:47

yes, take a look at the babashka repo, it's in src/babashka/impl/clojure/test.clj

borkdude13:03:40

also there is one for clojure.stacktrace

borkdude13:03:13

if you want to run / develop babashka locally, I recommend doing that with a JVM as to not have to compile it to test every little change

borkdude13:03:29

clone the repo with --recursive, it's something people often forget

borkdude13:03:50

I have a dev alias so I can run dev bb from anywhere with: clj -M:babashka/dev

pesterhazy13:03:44

You're right btw - while I can rebind clojure.test/report, this doesn't work

(with-redefs [clojure.stacktrace/print-cause-trace (fn [& args] (prn :BOOM))]
          (apply test/run-tests (filter contains-tests? nses)))

pesterhazy11:03:23

Gently dipping my toe into implementing this If that's ok I'll dump my thoughts here stream-of-consciousness style (don't hesitate to skip this or tell me to shut up)

pesterhazy11:03:50

So there's already nice stack trace printing https://github.com/babashka/babashka/blob/master/src/babashka/impl/error_handler.clj#L99

bb -e "(defn f [] (assert false)) (f)"
----- Error --------------------------------------------------------------------
Type:     java.lang.AssertionError
Message:  Assert failed: false
Location: <expr>:1:28

----- Context ------------------------------------------------------------------
1: (defn f [] (assert false)) (f)
                              ^--- Assert failed: false

----- Stack trace --------------------------------------------------------------
user/f - <expr>:1:1
user   - <expr>:1:28

pesterhazy11:03:44

What I understand from the above discussion is this: There's already babashka.impl.clojure.stacktrace, which at the moment simply defers to clojure.stacktrace. So the most natural place to implement sci-aware stacktrace printing would be providing a customized print-stack-trace

pesterhazy11:03:29

As a result, clojure.test would pick up better stack traces, but you'd also get better (pst) from the repl

user=> (defn f [] (assert false))
#'user/f
user=> (f)
java.lang.AssertionError: Assert failed: false [at <repl>:2:1]
user=> (pst)
AssertionError Assert failed: false
	java.lang.reflect.Constructor.newInstance (Constructor.java:490)
	sci.impl.Reflector.invokeConstructor (Reflector.java:310)
	sci.impl.interop/invoke-constructor (interop.cljc:78)
	sci.impl.analyzer/analyze-new/reify--4282 (analyzer.cljc:1084)
	sci.impl.analyzer/analyze-throw/reify--4242 (analyzer.cljc:968)
	sci.impl.analyzer/return-if/reify--4197 (analyzer.cljc:850)
	sci.impl.fns/fun/arity-0--1153 (fns.cljc:106)
	sci.lang.Var (lang.cljc:198)
	sci.impl.analyzer/return-call/reify--4474 (analyzer.cljc:1402)
	sci.impl.interpreter/eval-form (interpreter.cljc:40)
	babashka.impl.repl/repl/fn--27449 (repl.clj:81)
	babashka.impl.clojure.main/repl/read-eval-print--12639 (main.clj:103)

borkdude11:03:22

should be yes

pesterhazy11:03:11

So how about this as a plan: • Figure out how to customize functions in babashka.impl.clojure.stacktrace • Write a new print-stack-trace to behave like babashka.impl.error-handler/print-stacktrace • Write a unit test for the new function • Write an integration test similar to https://github.com/babashka/babashka/blob/master/test/babashka/test_test.clj#L16 • Optionally, make babashka.impl.error-handler use the new print-stacktrace function to reduce code duplication

borkdude11:03:56

sounds like a plan :) one challenge is how to unify the JVM stackstrace stuff with SCI's

pesterhazy11:03:33

Right. Do you want to see ONLY the sci stacktrace or both?

borkdude11:03:59

the SCI stackstrace shows both I think already

pesterhazy11:03:00

Maybe the sci-error print-stacktrace should be a separate function

borkdude11:03:12

or maybe that's only the bb error handler, not sure

borkdude11:03:28

I'd say first make a prototype and don't worry about the details

borkdude11:03:36

with the goal of making clojure.test behave better

pesterhazy11:03:07

Can't promise anything but will try

borkdude11:03:16

of course, no pressure

borkdude16:03:18

httpkit server with virtual threads in bb:

(require '[org.httpkit.server :as server])

(import '[java.util.concurrent Executors])

(server/run-server (fn [_]
                     {:body "Hello"})
                   {:worker-pool (Executors/newVirtualThreadPerTaskExecutor)
                    :port 11223})

@(promise)

🚀 6
jmv16:03:22

i'm really enjoying the new http-client. is there a plan to make it possible to set the default interceptors when constructing a client?

borkdude16:03:11

@UDXEK491P This is already possible today, but the interceptor namespace isn't available in bb itself. you can load it from source though when you include the http client library

borkdude16:03:29

and :interceptors is one of those options

jmv16:03:04

it doesn't seem like they get used: https://github.com/babashka/http-client/blob/main/src/babashka/http_client/internal.clj#L200 i tried doing this in a client but didn't have luck

{:request {:interceptors [,,,]}

borkdude16:03:34

aha, hmm, let me check

jmv16:03:45

would this work?

(or (:interceptors request-defaults)
    (:interceptors req)
    interceptors/default-interceptors)

borkdude16:03:02

ah I see, the request defaults are merged too late facepalm

jmv16:03:14

ahhh yep, makes sense

borkdude16:03:25

are you using it from bb or from jvm?

jmv16:03:13

jvm currently, but this library will be used for both bb scripts and jvm stuff

borkdude16:03:52

deps.edn or lein?

jmv16:03:14

i use lein for most things except bb tasks

borkdude16:03:28

ok, let me look into fixing it and then release a fix

jmv16:03:46

ty! no rush on cutting a release right away

borkdude19:03:40

@UDXEK491P published as v0.1.6

bananadance 2
gotta_go_fast 2
Chase19:03:58

The up arrow doesn't work for my when using bb. I get this:

λ ~/projects : bb
Babashka v1.1.173 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.

user=> ^[[A
Is there a way to fix that?

borkdude19:03:22

Try rlwrap bb

Chase19:03:11

Ok, that works. Should I just create an alias for bb='rlwrap bb' then?

borkdude19:03:14

you're running the butlast release btw, 1.2.174 is the latest which has the newer http-client built-in

borkdude19:03:39

I don't recommend replacing bb with rlwrap bb as this may cause issues, but use a different alias like bbr or so

Chase19:03:40

Ahh. But the cli app works! Lol

Chase19:03:53

But I will upgrade

borkdude19:03:59

yeah, it works, just some minor improvements which may be nice to have, just in case :)

Chase19:03:39

second question, how would you folks share a tiny bb cli to the community. It's like 40 lines. Should I throw it in a gist and tell people to run it like they do all bb scripts?

borkdude19:03:54

bbin is recommended for this

borkdude19:03:50

or you can distribute it as a normal deps.edn library, depends on the use case

borkdude19:03:09

deps.edn libraries can be used in bb in bb.edn

Chase19:03:00

I'm running bbin install but am getting this error:

----- Error --------------------------------------------------------------------
Type:     clojure.lang.ExceptionInfo
Message:  Invalid script coordinates.
If you're trying to install from the filesystem, make sure the path actually exists.
Data:     {:script/lib "", :procurer :http, :artifact :unknown-artifact}
Location: /home/chase/.babashka/bbin/bin/bbin:629:11

----- Context ------------------------------------------------------------------
625:           [:local :dir] (install-deps-git-or-local cli-opts' summary)
626:           [:local :file] (install-local-script cli-opts')
627:           [:local :jar] (install-local-jar cli-opts')
628:           [:maven :jar] (install-deps-maven cli-opts')
629:           (throw (ex-info "Invalid script coordinates.\nIf you're trying to install from the filesystem, make sure the path actually exists."
               ^--- Invalid script coordinates.
If you're trying to install from the filesystem, make sure the path actually exists.
630:                           {:script/lib (:script/lib cli-opts')
631:                            :procurer procurer
632:                            :artifact artifact})))))))
633:
634: (defn uninstall [cli-opts]

----- Stack trace --------------------------------------------------------------
babashka.bbin.scripts  - /home/chase/.babashka/bbin/bin/bbin:629:11
babashka.bbin.cli/run  - /home/chase/.babashka/bbin/bin/bbin:657:5
babashka.bbin.cli/run  - /home/chase/.babashka/bbin/bin/bbin:654:1
babashka.bbin.cli      - /home/chase/.babashka/bbin/bin/bbin:671:10
babashka.bbin.cli/bbin - /home/chase/.babashka/bbin/bin/bbin:706:5
babashka.bbin.cli/bbin - /home/chase/.babashka/bbin/bin/bbin:703:1
babashka.bbin.cli      - /home/chase/.babashka/bbin/bin/bbin:709:3
clojure.core/apply     - <built-in>
babashka.bbin.cli      - /home/chase/.babashka/bbin/bin/bbin:713:3
babashka.bbin.cli      - /home/chase/.babashka/bbin/bin/bbin:711:1

borkdude19:03:25

@U0CLCL6T0 Perhaps we can support the non-raw link

borkdude19:03:35

@U9J50BY4C can you post an issue about that?

Chase19:03:14

So I tried the raw and got this:

{:coords
 #:bbin{:url
        ""}}

borkdude19:03:16

Did the raw link work for you?

Chase19:03:17

did it work?

borkdude19:03:35

yes, you should now be able to execute chatgpt-cli if you added the bin dir to the path

Chase19:03:58

It works!

borkdude19:03:59

see bbin install instructions

borkdude19:03:21

you can also change the name with --as mychatgpt

Chase19:03:13

so I'll throw this up in @announcements Any suggestions on how I should describe using this? Have them install bbin? Alternatively, they can just take the file from the gist and run it with bb?

borkdude19:03:07

yep, many bb users already know bbin, but just downloading it also works

borkdude19:03:27

you can also put some install instructions in the gist

Chase19:03:31

oof, I forgot about this rlwrap issue. and it doesn't act quite like using bb to run this in the sense that I followed some other advice I got in another thread here to change my inputrc https://clojurians.slack.com/archives/C053AK3F9/p1677870509616049?thread_ts=1677868851.028919&amp;cid=C053AK3F9

borkdude19:03:04

you can remove that if it doesn't work for you

borkdude19:03:19

I think rlwrap has gone through some changes, it may no longer be necessary

Chase19:03:27

no it does work for me. but only when running clojure and bb. But I think if I wanted it to work for this new bbin install I would have to put

$if chatgpt-cli
    set enable-bracketed-paste off
$endif

Chase19:03:51

And without using rlwrap my up key doesn't work

borkdude19:03:20

You can also do this:

(when (= *file* (System/getProperty "babashka.file"))
  (when-not (babashka.fs/windows?)
    (when-not (str/includes? (.get (.command (.info (java.lang.ProcessHandle/current)))) "rlwrap")
      (println "Relaunching with rlwrap for better readline support")
      (babashka.process/exec "rlwrap bb" (str *file*)))))

borkdude20:03:02

haven't tested it, but something like this

Chase20:03:03

ahh, cool. I will bookmark that comment. For now just throwing in alias chat="rlwrap chatgpt-cli" works super fast. lol

borkdude20:03:16

that may be better ;)

Chase20:03:16

If I start installing a ton of bb scripts I'll look into a better fix

Chase20:03:41

thanks, this is awesome btw. Super quick and painless to convert over from my .clj file

👍 2
borkdude20:03:28

Some more ideas for reading input from the console: https://rattlin.blog/bbgum.html gum is very cool, yet you will have a dependency that people have to install. There is also a library for bb for it, but shelling out to it should be easy as well. https://github.com/lispyclouds/bblgum

Chase20:03:24

I'll check it out.

borkdude20:03:04

btw the rlwrap hack from above didn't work, this is a better version:

(require '[babashka.fs]
         '[babashka.process])

(defn read-loop []
  (while true
    (prn (read-line))))

(when (= *file* (System/getProperty "babashka.file"))
  (if-not (babashka.fs/windows?)
    (if-not (System/getenv "BB_RLWRAP")
      (do (println "Relaunching with rlwrap for better readline support")
          (babashka.process/shell {:extra-env {"BB_RLWRAP" "true"}}
                                  "rlwrap" "bb" (str *file*)))
      (read-loop))
    (read-loop)))

Chase20:03:29

bookmarked, thanks again

Chase21:03:48

sorry to borry you again @U04V15CAJ but I think adding those comments in messes up the script somehow. How should I put those comments? I get this error now if trying to just run it like ./chatgpt-cli

----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  No reader function for tag You

Chase21:03:27

Also, if I alter the gist and then run the bbin install ... again it fetches the new info right or is it a one install from the gist only?

borkdude21:03:09

it always fetches the new one

borkdude21:03:26

well it depends on what sha you give it of course

borkdude21:03:51

in clojure you write comments with:

;;

Chase21:03:21

oh you use clojure comments, not bash comments!

borkdude21:03:06

of course, it's clojure :)

Chase21:03:46

lol! Yeah I feel silly. It was the shebang at the top of the file that got me all discombobulated