babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
borkdude 2021-06-10T10:40:51.002500Z

New babashka release: 0.4.5 Babashka proper: - Add java.net.InetSocketAddress - Add support for slingshot https://github.com/babashka/babashka/issues/675 - Add STM facilities (`dosync`, ref, etc.) - Fix .wait, .notify interop on arbitrary classes Deps.clj (used for resolving deps and clojure invocations): - Fix JVM option parsing https://github.com/borkdude/deps.clj/issues/46 Sci: various minor performance improvements. https://github.com/babashka/babashka/blob/master/CHANGELOG.md#045

👍 1
6
❤️ 3
🎉 1
emilaasa 2021-06-10T11:29:59.005Z

I'm a real noob at bb, and at running "imperative" commands from clj at all. How would you structure a pretty simple script that is supposed to do about this thing, here in zsh loop:

for i in `seq 1 100`; do
echo $i >> main.go
git add .
git commit -m $i
;done

borkdude 2021-06-10T11:33:42.006600Z

@emilaasa for translates to doseq in clojure (used for side effects. seq 1 100 is (range 1 100) (not sure about inclusive/exclusive in bash). The echo call can be done using (spit "main.go" i :append true) Calling git can be done using shelling out e.g. with clojure.java.shell or babashka.process or in tasks using shell

emilaasa 2021-06-10T11:34:55.006900Z

Thanks I'll try with doseq, I did reach for that but I think I messed up 🙂

borkdude 2021-06-10T11:37:33.007100Z

Just use println when you're not sure, print things and you will figure it out

emilaasa 2021-06-10T11:40:19.007300Z

Ah great it works exactly the same with waiting for shell output and everything!

(doseq [i (range 100)]
  (append-to-file "main.go" (gofunc (str "funfunc" i)))
  (gofmt "main.go")
  (add "main.go")
  (commit "asdf"))

emilaasa 2021-06-10T11:41:00.007500Z

Thanks a lot - as normal with a good newbie question I feel stupid now 😄

borkdude 2021-06-10T11:41:31.007700Z

no need, this channel is n00b question friendly!

emilaasa 2021-06-10T11:42:18.007900Z

These implicit (or explicit let's be honest) have tripped me up before

Endre Bakken Stovner 2021-06-10T16:52:14.010700Z

I am still unable to capture stderr in babashka/process:

(require '[babashka.process :as p :refer [process]]
           '[<http://clojure.java.io|clojure.java.io> :as io])
  (def c (process ["bash" "-c" "echo An error message &gt; /dev/stderr"] {:err :inherit :shutdown p/destroy}))
  (with-open [rdr (io/reader (:out c))]
    (binding [*in* rdr]
      (loop []
        (let [line (read-line)]
          (println :line line)
          (when (not (nil? line))
            (recur))))))
prints
An error message
:line nil
I was expecting
:line An error message
:line nil
Any hints?

Endre Bakken Stovner 2021-06-10T16:52:21.010900Z

Can you reproduce? This happens in both the rebl and the cider repls.

borkdude 2021-06-10T16:53:44.011100Z

What are you expecting this example to do?

borkdude 2021-06-10T16:54:21.011300Z

You are reading from the process's stdout, not stderr right

Endre Bakken Stovner 2021-06-10T16:54:38.011500Z

But does not :inherit merge the two?

borkdude 2021-06-10T16:55:09.011700Z

No, :inherit writes directly to the parent's corresponding stream

Endre Bakken Stovner 2021-06-10T16:55:23.012Z

😳

borkdude 2021-06-10T16:56:22.012200Z

The name is adopted from the Java API: https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#inheritIO()

borkdude 2021-06-10T16:57:13.012400Z

This works:

(require '[babashka.process :as p :refer [process]]
         '[<http://clojure.java.io|clojure.java.io> :as io])
(def c (process ["bash" "-c" "echo An error message &gt; /dev/stderr"]
                {:shutdown p/destroy}))

(with-open [rdr (io/reader (:err c))]
  (binding [*in* rdr]
    (loop []
      (let [line (read-line)]
        (println :line line)
        (when (not (nil? line))
          (recur))))))

borkdude 2021-06-10T16:57:34.012600Z

Note: I did not set :err :inherit and I read from :err, not :out

Endre Bakken Stovner 2021-06-10T16:58:15.012800Z

I see. redirectErrorStream is perhaps what I want: https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#inheritIO()

borkdude 2021-06-10T16:58:59.013Z

Ah I see

borkdude 2021-06-10T16:59:21.013200Z

you could also do {:out *out* :err *out*}

borkdude 2021-06-10T16:59:35.013400Z

or write to a custom stringwriter

Endre Bakken Stovner 2021-06-10T17:00:08.013600Z

But it might be nice to be able to distinguish stderr and stdout also. Is there a way to read both at the same time? Thanks for the help btw!

borkdude 2021-06-10T17:00:22.013800Z

yes, just start two such loops

🙏 1
Endre Bakken Stovner 2021-06-10T17:04:04.014100Z

I will try. I'd imagine one would have to finish before the other begins, but I'll test it out.

borkdude 2021-06-10T17:45:45.014500Z

well, you could run them side by side in a thread or so

Endre Bakken Stovner 2021-06-10T17:46:51.014700Z

That is what I did 🙂 (.start (Thread. my-loop)). I'm used to multithreading stuff being such a pain in the behind. That seems to be one aspect of the language which is easier in Java than in Python

borkdude 2021-06-10T18:05:08.014900Z

you can also do (future ..)