babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
wilkerlucio 2021-04-27T02:11:06.144Z

if you mean to add variables when calling shell, you can use:

(shell {:extra-env {"SOME" "VAR"}} "your command")

kokada 2021-04-27T02:48:36.144400Z

No, in this case I really need to overwrite the environment variables while the script is running

kokada 2021-04-27T02:48:49.144600Z

Like doing a export ENV on shell

kokada 2021-04-27T02:50:25.144800Z

For now my workaround is to use the #_(<shell code here>) trick described on Babashka's book (https://book.babashka.org/#_running_a_script) to edit the environment variables, but this is ugly

kokada 2021-04-27T02:51:32.145100Z

Specially because I can't define a shell function, since this would cause an error because Clojure will try to interpret anything inside {} as a map (and fail to parse it

kokada 2021-04-27T02:53:54.145300Z

BTW, it is also possible to change an environment variable in Python I found it curious that even the Java solutions involved doing some magic since it seems that Java itself doesn't have a method for it

mike_ananev 2021-04-27T07:30:33.147200Z

@thiagokokada you can do it like this

(shell (format "env VAR1=%s VAR2=%s %s" "var1" "var2" "ls -la")

mike_ananev 2021-05-01T17:52:48.336400Z

@thiagokokada https://gist.github.com/mikeananev/c87c1596aed50b7bb095a816f6921737 you can read env vars for the current process (see line 14) and then modify them as usual map.

kokada 2021-05-01T18:00:11.336600Z

I may have understand wrong, but in this case I really need to export the environment variables again

kokada 2021-05-01T18:00:53.336800Z

I can of course inject then in every shell call and every usage in my Clojure program, but this get old really quickly

borkdude 2021-04-27T07:31:46.148200Z

@mike1452 the above can be done better by passing a map with :extra-env as the first arg:

(shell {:extra-env {"FOO" "BAR"}} "ls -la")

mike_ananev 2021-04-27T09:42:12.150200Z

Cool.

borkdude 2021-04-27T09:43:41.150800Z

There is also :env to overwrite all env vars. These are the same options as in babashka.process

borkdude 2021-04-27T09:44:10.151100Z

You can also use :out "foo" :err "log.txt" to write to a file

mike_ananev 2021-04-27T10:14:02.151700Z

what is fqdn of shell ? babashka.process ? can't find it there

borkdude 2021-04-27T10:15:17.152500Z

@mike1452 shell is a variant of babashka.process tweaked more towards usage in bb.edn. It is automatically imported from babashka.tasks

mike_ananev 2021-04-27T10:16:05.152900Z

Thanks! Now it works

bb -e '(babashka.tasks/shell  {:extra-env {"FOO" "BAR"}} "env")'

mike_ananev 2021-04-27T10:18:25.153200Z

bb -e '(babashka.tasks/shell  {:env {"FOO" "BAR"}} "env")'

mike_ananev 2021-04-27T10:19:02.153800Z

I wanted to check env settings from one line script.

kokada 2021-04-27T13:04:43.156200Z

Like I said in the above thread, I want to change the current environment variables for the program, not for a subprocess

kokada 2021-04-27T14:01:25.157Z

Maybe this will interest someone, it is a modification of test_runner.clj that automatically discovers test files: https://gist.github.com/thiagokokada/fee513a7b8578c87c05469267c48e612

🚀 3
borkdude 2021-04-27T14:09:13.157100Z

awesome!

🙌 1
2021-04-27T14:37:31.160200Z

FYI, i’ve been playing with autocompletion on the command line. I’ve created a small POC that could maybe grow into something bigger. It’s inspired by how the aws cli tool is structured and can do autocompletion in the same way. The responsiveness is much better though 😎 https://github.com/jeroenvandijk/matryoshka

👍 2
😎 3
2021-04-27T14:38:32.160400Z

@russell.matney I started with your work as inspiration, but i couldn’t figure out how to do nested completions. I’m not sure if the AWS approach is better or not, but it works

🤘 1
2021-04-27T14:39:13.160900Z

(forgot the link)

borkdude 2021-04-27T14:46:25.161200Z

https://github.com/jeroenvandijk/matryoshka/blob/9f70e63418b7b9ee7a58255d83a392da4b7f35de/matryoshka#L83 This is not a "doesn't work yet" problem, but a problem that aliases are only valid in the next top level s-expression. You should use resolve to resolve a fully qualified symbol, if you are in the same expression.

borkdude 2021-04-27T14:48:04.161600Z

Clojure 1.10.1
user=> (defn foo [] (require '[clojure.set :as set]) (set/union #{1 2 3} #{4 5 6}))
Syntax error compiling at (REPL:1:47).
No such namespace: set

2021-04-27T14:48:39.161800Z

Yeah indeed. I guess I have to have a better look at what you did in bb tasks. This was a quick “addon” for now (i should have left it out)

borkdude 2021-04-27T14:49:20.162Z

bb tasks pushes all the :requires to the top level

borkdude 2021-04-27T14:59:51.162700Z

@jeroenvandijk would your solution work for both bash / zsh? it would be very nice :)

2021-04-27T15:01:30.163600Z

I’m using zsh, not sure about bash, but I’m guessing if we try we could even make it work for Windows 🙂 It uses the same approach as the AWS tool https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-completion.html#cli-command-completion-linux

borkdude 2021-04-27T15:02:36.164900Z

🤯

2021-04-27T15:02:39.165100Z

The output is slightly different from what @russell.matney did. Maybe the underlying framework is different

2021-04-27T15:04:47.166100Z

I don’t know if this is the way for bash, but in my (basic) bash shell it doesn’t work:

bash-3.2$ autoload bashcompinit && bashcompinit
bash: autoload: command not found
bash-3.2$ autoload -Uz compinit && compinit
bash: autoload: command not found
bash-3.2$ compinit
bash: compinit: command not found
bash-3.2$ export PATH=".:$PATH"
bash-3.2$

2021-04-27T15:05:34.166500Z

not out of the box at least 😅

russmatney 2021-04-27T15:36:49.170400Z

@jeroenvandijk really cool!

russmatney 2021-04-27T15:37:28.170900Z

i'll have to dig into the implementation later today

russmatney 2021-04-27T15:37:48.171500Z

the other thing that keeps coming to mind is wanting to support all of bb's cli opts, not just tasks

👍 2
borkdude 2021-04-27T15:37:52.171800Z

Hmm, crap, if you have :deps in bb.edn but if you also have deps.edn, those deps.edn deps are actually also downloaded and added to the classpath ;)

➕ 1
😅 1
2021-04-28T09:33:49.218900Z

+1 here. I ran into the above described situation as well. I can confirm it can give unexpected errors and slower load time

borkdude 2021-04-28T09:37:29.219200Z

in which case?

borkdude 2021-04-28T09:39:21.219400Z

slower as in what, can you be more specific? btw, I am working on a fix as we speak

borkdude 2021-04-28T10:16:52.219600Z

it should be fixed now. try one of the binaries from #babashka-circleci-builds

2021-04-28T11:59:42.219800Z

Cool 🙂

2021-04-28T12:01:51.220Z

The case where it was giving me unexpected results was when I had my custom bb tasks runner script and giving it empty {:deps {} } . So I wasn’t expecting anything, however the deps.edn in that directory had an error, so the whole call failed. But the script I was trying to run was a hello world (without deps), so it was confusing at first

2021-04-28T12:02:28.220200Z

Normally this hello world would be quick, but due to the (failing) deps it was slower

2021-04-28T12:02:45.220400Z

i’ll try the new binary!

borkdude 2021-04-28T12:02:47.220600Z

I'll add another check for an empty deps map, since it doesn't have to call out to tools.deps in that case

2021-04-28T12:47:09.220800Z

so far everything works. Calling tools.deps with an empty map adds 10ms. Not major

borkdude 2021-04-28T12:47:38.221Z

cool

2021-04-27T15:47:07.172700Z

@borkdude I’ve fixed the :deps and :requires “feature”. This works now https://github.com/jeroenvandijk/matryoshka/blob/main/tasks/custom.edn

borkdude 2021-04-27T15:48:16.173200Z

nice! is this about completion or also about building an alternative task runner?

2021-04-27T15:49:30.173400Z

I don’t know yet. I am looking for something that I can use or all my projects. The autocompletion makes this actually feasible. You start with a category and the suggestions help you navigate

2021-04-27T15:50:13.173600Z

I was thinking of wrapping these commands https://github.com/practicalli/clojure-deps-edn so that I can use them everywhere without having to do constant lookups

borkdude 2021-04-27T15:51:45.173900Z

what are you currently missing from bb.edn's task runner?

2021-04-27T15:52:09.174100Z

I’m not sure if I’m missing something other than the global part

borkdude 2021-04-27T15:52:47.174300Z

how does your task runner implement "global" ness?

2021-04-27T15:54:00.174700Z

good question. Not in some particular way, but the difference with babashka tasks is that all the tasks are isolated and it has a tree structure so it should stay fast

2021-04-27T15:55:21.174900Z

I’m not saying this could not be part of babashka tasks and that this is better (i just started working on it today so it’s nothing really). I don’t know yet where this will end. When I have a structure I like I’ll try to see what the main differences are

borkdude 2021-04-27T15:55:28.175100Z

fast in what sense?

2021-04-27T15:56:37.175300Z

If I have a global library of tasks this could easily become really big. So code loading would be an issue if you are not careful. If you try the aws cli you feel the difference 🙂

2021-04-27T15:57:06.175500Z

But i think it’s a bit premature to talk about my “benefits”. I’m not actually using it for something

borkdude 2021-04-27T15:57:37.175700Z

well, it's good to take future use case into account without locking down the design to exclude that possibility right now, that's why I am asking

2021-04-27T15:58:46.175900Z

Especially the autocompletion needs to stay fast for a nice experience

2021-04-27T15:59:07.176100Z

The #include is lazy loading here https://github.com/jeroenvandijk/matryoshka/blob/main/tasks.edn#L1

borkdude 2021-04-27T16:00:29.176400Z

cool :)

2021-04-27T16:00:30.176600Z

So you don’t get hit by a huge startup penalty when you add many libraries. It’s only about the nesting. So a nesting of 4 would mean having to load 4 of these files

2021-04-27T16:00:53.176800Z

instead of something to the power of 4

borkdude 2021-04-27T16:01:02.177Z

I think these things can also be implemented using normal keywords instead of reader tags btw

borkdude 2021-04-27T16:01:27.177200Z

right now a pretty large bb.edn still loads in 1ms

borkdude 2021-04-27T16:01:45.177400Z

it's first parsed as EDN only and only the task that is executed is actually re-parsed as code

2021-04-27T16:02:00.177600Z

ah yeah so i’m guessing it’s a bit premature

2021-04-27T16:02:14.177800Z

i was also thinking what if you could add a module

2021-04-27T16:02:34.178Z

i was thinking you could have an aws module and it would look like this file

2021-04-27T16:03:32.178200Z

that was my fantasy at least 😅 Not sure what parts are actually required for this to work

2021-04-27T16:04:27.178400Z

I’m curious how you would use keywords instead of the reader tags btw

2021-04-27T16:05:53.178600Z

(I stole the #include idea from https://github.com/juxt/aero btw. That one is not lazy though)

borkdude 2021-04-27T16:05:54.178900Z

{:cmds {aws {:cmds "tasks/aws.edn"}}}
perhaps? :)

2021-04-27T16:06:20.179100Z

haha hmmm no that would be too simple 😛

2021-04-27T16:06:34.179300Z

fair enough, that would be better

borkdude 2021-04-27T16:06:35.179500Z

yeah, I know that lib. personally I would like to avoid reader tags a little bit, but maybe my feeling isn't justified on good reasons

2021-04-27T16:07:13.179700Z

no i think you are right, probably better to keep it simple

2021-04-27T16:26:41.180Z

Note sure if it is related, but I noticed that babashka.deps/add-deps doesn’t complain when I give it rubbish

emilaasa 2021-04-27T16:30:20.181Z

I've been in a few programming language chats and one popular topic / channel was #naming-things

emilaasa 2021-04-27T16:30:27.181300Z

Maybe we need that here as well? 🙂

✅ 2
dharrigan 2021-04-27T16:36:01.181500Z

ha! what a great idea

borkdude 2021-04-27T17:00:26.181900Z

what kind of rubbish

borkdude 2021-04-27T17:00:36.182100Z

it just passes stuff through to tools.deps basically

borkdude 2021-04-27T17:01:03.182300Z

and tools.deps picks up on the local deps.edn

2021-04-27T18:54:46.183Z

I didn't add the '{:deps ...}' wrapping and I was wondering why my require wasn't working. So not really rubbish, but it was invalid config

2021-04-27T20:00:02.188200Z

I'm trying to make a babashka project with a structure that mirrors a clojure one, and I want a test task that comes with the test dir added to the classpath. First I tried this, but it looks like there's no :extra-paths like in deps.edn

{:paths ["src"]
 :tasks
 {test {:extra-paths ["test"]
        :requires ([foo.test-runner :refer [run]])
        :task (run)}}}
Then I tried to work around it, but it looks like the require needs to be in a separate expression from where it's used, so this doesn't work either.
{:paths ["src"]
 :tasks
 {test {:requires ([babashka.classpath :as cp])
        :task (do (cp/add-classpath "test")
                  (require '[foo.test-runner :refer [run]])
                  (run))}}}
I also tried something similar with requiring-resolve , but no luck. Any suggestions?

borkdude 2021-04-27T20:05:15.189300Z

@madstap tasks do not (yet) support :extra-paths. you can take a look at how @thiagokokada did it here: https://clojurians.slack.com/archives/CLX41ASCS/p1619532085157000

borkdude 2021-04-27T20:06:11.190300Z

you could just add the test dir to the classpath in the script and load the script using (load-file ...) in the task

2021-04-27T20:07:35.191500Z

The test-runner script would have to be on the classpath then, for me to be able to run it as a task, or I'd have to run it as a standalone script

borkdude 2021-04-27T20:08:37.191900Z

you can run standalone scripts with load-file without adding them to the classpath

2021-04-27T20:09:05.192700Z

Oh, right, sorry, didn't catch that. Yeah, that works

borkdude 2021-04-27T20:09:05.192800Z

you could first use load-file and then call a function from that script, that would work too

2021-04-27T20:12:51.193400Z

Maybe I'm missing something, but this doesn't work

{:paths ["src"]
 :tasks
 {test {:task (do (load-file "test/foo/test_runner.clj")
                  (require '[foo.test-runner])
                  (foo.test-runner/run))}}}

borkdude 2021-04-27T20:13:17.194Z

what exactly doesn't work here?

2021-04-27T20:13:29.194400Z

The file does get loaded, but I'm not able to call the function

borkdude 2021-04-27T20:13:33.194600Z

you probably don't need the require since you already loaded the file

borkdude 2021-04-27T20:13:57.195100Z

but it should not hurt

2021-04-27T20:14:18.195500Z

I get a ^--- Could not resolve symbol: foo.test-runner/run

borkdude 2021-04-27T20:14:59.196100Z

hmm, right. this is the gilardi scenario again.

borkdude 2021-04-27T20:15:26.196800Z

a bit ugly but ((requiring-resolve 'foo.test-runner/run)) should work

2021-04-27T20:15:33.197Z

That sounds ominous

borkdude 2021-04-27T20:15:39.197200Z

or simply resolve

borkdude 2021-04-27T20:16:23.197500Z

The gilardi scenario is basically this:

user=> (defn foo [] (require '[clojure.set :as set]) (set/union #{1 2 3} #{4 5 6}))
Syntax error compiling at (REPL:1:47).
No such namespace: set

borkdude 2021-04-27T20:16:40.197900Z

The reader has to know about the alias (or namespace) set already before the requires has happened

2021-04-27T20:17:26.198600Z

requiring-resolve works! thanks

2021-04-27T20:17:45.198800Z

I see, that makes sense

borkdude 2021-04-27T20:18:12.199300Z

I am considering an :enter step which is a hook before the task gets executed

borkdude 2021-04-27T20:18:21.199600Z

this is for logging the task name for example

borkdude 2021-04-27T20:18:30.199900Z

but possibly it would also solve this, not sure...

borkdude 2021-04-27T20:19:07.200600Z

Maybe introducing aliases is better for this

2021-04-27T20:19:12.200900Z

I guess that depends on whether the enter step is ran before reading the task code

2021-04-27T20:19:38.201700Z

or analyzing, maybe

borkdude 2021-04-27T20:20:30.202600Z

:aliases {:test {:extra-paths ["test"]}}
:tasks {test {:aliases [:test] :task foo.test-runner/run}}

2021-04-27T20:21:25.202900Z

Yeah, that would solve it nicely

2021-04-27T20:22:35.204100Z

Are aliases preferable to an :extra-paths key in the task?

:tasks {test {:extra-paths ["test"] :task foo.test-runner/run}}

borkdude 2021-04-27T20:23:36.205200Z

dunno :)

borkdude 2021-04-27T20:23:54.205400Z

I guess it's not too hard to support

borkdude 2021-04-27T20:25:33.206900Z

I think one could also do it like this, perhaps:

{:tasks {-add-test-cp (babashka.classpath/add-classpath "test"),
           test {:depends [-add-test-cp]  :task foo.test-runner/run}
could you try that, just for fun...?

2021-04-27T20:25:50.207400Z

Sure 🙂

borkdude 2021-04-27T20:25:57.207700Z

(indenting in slack is hard)

2021-04-27T20:28:01.208100Z

It works

borkdude 2021-04-27T20:29:02.208300Z

:-D

2021-04-27T20:31:41.209100Z

Easier on the eyes than the requiring-resolve dance, I think

2021-04-27T20:32:19.209600Z

This doesn't work though.

{:paths ["src"]
 :tasks {-add-test-cp (babashka.classpath/add-classpath "test"),
         test {:depends [-add-test-cp]
               :requires ([foo.test-runner :refer [run]])
               :task (run)}}}

borkdude 2021-04-27T20:52:13.209700Z

that doesn't work because the :requires are processed on the top level before anything else

borkdude 2021-04-27T20:53:43.210100Z

it should work when you do it like this: :task (do (require ...) (run)

borkdude 2021-04-27T20:54:45.210300Z

But maybe this is fixable. I think it is. I'll make an issue for this.

borkdude 2021-04-27T21:05:14.211Z

Maybe just adding :extra-paths is nicer though. I wonder how common this is

borkdude 2021-04-27T21:33:54.211700Z

@madstap I pushed support for :extra-paths and :extra-deps in tasks to master now. Are you willing to take it for a spin?

borkdude 2021-04-27T21:36:34.212600Z

Maybe we won't ever need aliases if we support it like this

borkdude 2021-04-27T21:37:14.213200Z

since you can depend on a task that adds extra-deps and extra-paths as a sort of alias

2021-04-27T21:37:17.213400Z

wow, that was fast! 🔥

2021-04-27T21:38:16.214500Z

Hmm, yeah, then tasks kinda serve as aliases as well

2021-04-27T21:38:38.214900Z

I'll check it out

borkdude 2021-04-27T21:39:17.215300Z

are you using macos or linux?

2021-04-27T21:39:22.215600Z

linux

borkdude 2021-04-27T21:39:22.215700Z

or windows

borkdude 2021-04-27T21:39:39.216100Z

ok, here is a binary: https://17876-201467090-gh.circle-artifacts.com/0/release/babashka-0.3.7-SNAPSHOT-linux-amd64.tar.gz fresh from #babashka-circleci-builds

2021-04-27T21:39:57.216300Z

nice

2021-04-27T21:43:22.217100Z

Looks like it works

borkdude 2021-04-27T21:43:48.217400Z

cool so :tasks {test {:extra-paths ["test"] :task foo.test-runner/run}} it is then

🤘 1