Fork me on GitHub
#babashka
<
2019-12-20
>
laheadle00:12:18

Really enjoying babashka. Life's too short to remember how to write bash code. I feel liberated. Thanks a million @borkdude!

borkdude11:12:11

Can I quote this line in the README of babashka? Like I did here with another lib:

borkdude15:12:01

I added this now: https://github.com/borkdude/babashka/blob/master/README.md Can you check if you still agree?

nate_clojurians03:12:52

is there a way to get the current source file?

nate_clojurians03:12:02

the path to it, really

sogaiu04:12:01

@nate_clojurians borkdude may be around later to give you an answer

nate_clojurians05:12:18

hmmm could really use re-quote-replacement

nate_clojurians05:12:01

I guess this works?

(defn re-quote-replacement
  [^String replacement]
  (apply str (map #(case %
                     \\ "\\\\"
                     \$ "\\$"
                     %)
                  replacement)))

nate_clojurians07:12:51

it would be nice to have more file handling stuff available as well, similar to what joker makes available

borkdude07:12:07

@nate_clojurians can you give an example of what exactly you need and why you need it in an issue?

borkdude08:12:09

Iā€™m not aware that Clojure itself provides the name of the current file, but it does provide the name of the current namespace

borkdude08:12:53

Due to a typo re-quote-replacement is not available... I'll fix the typo. Sorry about that šŸ™‚

borkdude08:12:10

Fixed on master:

$ lein bb '(clojure.string/re-quote-replacement "string \\ $")'
"string \\\\ \\$"

borkdude08:12:41

Ah, Clojure can do this:

(def x 1)
(println (:file (meta #'x)))
$ clj /tmp/foo.clj
/tmp/foo.clj
So that would be nice to add I guess.

borkdude09:12:21

@plexus Is your blog open source? If you're open to it, I could do a PR to update *in* to <input>

borkdude09:12:04

I added a list of currently known blog articles about babashka: https://github.com/borkdude/babashka#blogs

borkdude12:12:33

Considering clj-http-lite for bb:

$ bb "(require '[clj-http.lite.client :as client]) (:status (client/get \"\"))"
200

borkdude13:12:40

Rationale: idiomatic http client. clj-http has been around for a long time, "defacto" lib, but vanilla clj-http doesn't work with GraalVM. clj-http-lite is the GraalVM version that comes closest

borkdude13:12:05

Alternative: expose necessary Java classes to build your own requests (but contrary to java.time that seems tedious)

borkdude14:12:40

Thanks. Btw the fix for re-quote-replacement has been released

borkdude14:12:09

$ bb -e "(require '[clj-http.lite.client :as client]) (client/post \"\" {:body (json/generate-string {:a 1})})" | bb '(keys <input>)'
(:headers :status :body)

borkdude14:12:23

maybe adding the client default alias makes sense

borkdude14:12:37

or http.client maybe?

borkdude14:12:08

Naming is really the hardest problem

nate_clojurians14:12:13

definitely http.client. the potential for client to be used by other things seems pretty high

borkdude14:12:05

yeah maybe I'll leave out a default alias altogether then

nate_clojurians14:12:18

the joker stdlib is probably a good place to look for inspiration on what kind of stuff to include https://candid82.github.io/joker/

nate_clojurians14:12:53

filepath in particular is nice, since scripts often are trying to manipulate things on the filesystem

borkdude14:12:27

@nate_clojurians Again, could you give an example (or maybe an issue) with how that is supposed to work? I commented on it above

nate_clojurians14:12:06

i'm on my phone right now but will be on a computer in a bit

borkdude14:12:30

@nate_clojurians If you mean the joker.filepath namespace: there is support for Java interop in babashka for .File, java.nio.* + the namespace. This should give you what you need while also maintaining compatibility with normal Clojure

nate_clojurians15:12:41

I've been leaning on those pretty heavily

nate_clojurians15:12:40

including java.nio.file.Files would let me safely make symbolic links without shelling out

sogaiu15:12:45

it's nice to be able to make symlinks for sure -- unfortunately, recent experiments suggest this won't work on windows 10 until jdk 13 šŸ˜ž

nate_clojurians15:12:37

Files also has readlink for symlinks

borkdude15:12:46

@sogaiu are you using Windows a lot?

sogaiu15:12:45

i use it to test what i'm building

borkdude15:12:32

@sogaiu what about using WSL(2)

sogaiu15:12:26

wsl2 is not an option yet iiuc -- also i am using vms where it is questionable whether it will be practical to use.

borkdude15:12:02

it seems to be "Insider" right

borkdude15:12:21

but wsl1 is there already

sogaiu15:12:37

why go to the old thing?

borkdude15:12:09

because the new thing was not an option?

sogaiu15:12:01

i am skeptical of the wsl approach as being an interim bandaid solution -- wsl2 probably exists for a reason...one of thoese being that wsl was not good enough?

sogaiu15:12:29

perhaps other reasons?

borkdude15:12:48

I think wsl2 is faster because better native support

borkdude15:12:36

I believe they removed an intermediate layer or something

borkdude15:12:57

I guess asking in #clj-on-windows about experiences may be worth it

sogaiu15:12:06

if possible, i'd like what i build to run with less requirements -- it's unclear to me whether using wsl2 is going to be a worthwhile trade-off

sogaiu15:12:15

sure -- i'd like to try wsl2 out myself, so i've been waiting.

borkdude15:12:32

I posted a question in the channel myself, I'm also curious

borkdude15:12:28

> Follow the official instructions to install the clojure cli tools in bash in WSL. Cursive will use its own, built-in version for now (see below), although the Clojure CLI tools for Windows are coming.

sogaiu15:12:34

seems like a nice article, thanks

sogaiu15:12:44

it mentions the long classpath issue -- cursive apparently has its work-around. btw, i took timgilbert's pathing jar efforts (TDEPS-120) and made this: https://github.com/sogaiu/clj-pathing-jar

sogaiu15:12:47

btw, i mention this pathing jar thing, because i have succeeded in using it (with some modifications) to build a native-image executable directly with native-image on windows. so it's not necessary to build an uberjar first.

sogaiu15:12:08

on a related note, i've been talking to taylorwood about some related issues in clj.native-image -- may be eventually that will be usable for windows use.

sogaiu15:12:07

i like the idea of being able to determine the current file location. (as a side note, unless it's going to be a dynamic var, i'm not a fan of using the earmuffs.)

borkdude15:12:16

is it a dynamic var in joker? I think it could be <file>, since we already have <input>

nate_clojurians15:12:28

yeah, <file> seems better here

borkdude15:12:28

although clojure has *command-line-args* which is a bit inconsistent I guess, but maybe that was introduced before the earmuffs convention

nate_clojurians15:12:45

that's fixable, too šŸ˜‰

borkdude15:12:48

Neh, I'm going to try to be compatible with clojure as much as I can

borkdude15:12:30

@nate_clojurians What is the value of file in a script that you use with require in joker

nate_clojurians15:12:24

if A requires B, then <file> in B is the location of B

borkdude15:12:13

Oh btw, it seems like *command-line-args* is a dynamic var:

(binding [*command-line-args* 2])

borkdude15:12:13

Darn. Maybe it makes sense to introduce *input* instead of <input> then, because it will be bound by babashka itself to some value

borkdude15:12:47

And call <file> just *file*

borkdude15:12:16

Welcome to joker v0.14.0. Use EOF (Ctrl-D) or SIGINT (Ctrl-C) to exit.
user=> (binding [*file* 2])
nil

sogaiu15:12:06

as long as the thing is going to be a dynamic var and not change its name, i think it makes sense to use the earmuffs

nate_clojurians15:12:30

it's nice for testing to be able to bind to something else, too

borkdude15:12:49

yeah, that hadn't occurred to me when renaming *in* to *input*

borkdude15:12:04

(which wasn't and isn't a dynamic var, but can be made so)

nate_clojurians15:12:27

it seems like a good move

nate_clojurians15:12:57

it's not even 0.1 yet, do some breaking changes ā¤ļø

borkdude15:12:15

yeah, that's why it isn't 0.1 yet.. still figuring this out šŸ™‚

sogaiu15:12:18

i haven't played enough with *in* / *input* / <input> to have an opinion about whether it should be a dynamic var -- may be other people are in a better position to have an informed opinion šŸ™‚

borkdude15:12:56

well, <input> is really a delay which will be realized the first time it's evaluated

nate_clojurians15:12:57

anything that lets us easily fake things out for testing is a big win imo

borkdude16:12:27

so if you don't use <input> in your program, it won't block, waiting for input

borkdude16:12:00

but if you use it twice, it will be bound to the same value

borkdude16:12:29

$ echo 2 | bb '(* <input> <input>)'
4

nate_clojurians16:12:44

<input> is a seq, I thought

sogaiu16:12:06

it depends on the command line options iiuc

borkdude16:12:07

@nate_clojurians It reads EDN by default

borkdude16:12:52

it does so by default to make chaining EDN expressions more succinct

nate_clojurians16:12:25

that makes sense. making it have two meanings is tricky but manageable

borkdude16:12:43

I think keeping the notation for <input> might make sense, since it is a bit magic in this respect

borkdude16:12:01

instead of *file* which is just an ordinary dynvar

nate_clojurians16:12:24

if I wanted to rebind the <input> for testing, how would I do that?

borkdude16:12:21

look at the babashka tests, I haven't found the need for that

borkdude16:12:36

just feed input to the script

borkdude16:12:40

with with-in-str etc

borkdude16:12:39

This is more for one-liners, not really for scripting, where you can just use read-line et al

nate_clojurians16:12:55

so rebinding *in* instead of input. makes sense to me

nate_clojurians16:12:24

sorry if I sound overly confused about the details here. I've just been writing a script with a shebang and not writing one-liners. just trying to be a rubber duck :)

borkdude16:12:02

babashka started out as a tool to do just little sprinkles of clojure in between bash expressions, but now it's growing more towards a full scripting solution

nate_clojurians16:12:04

the scripting bit is what mostly interests me, replacing the scattered bits of bash across my clojure projects

nate_clojurians16:12:51

stuff I'd use ruby or python for when I need a little more involved scripting but no real bundling or libraries

sogaiu16:12:04

i have a similar interest -- am hoping eventually for a crossplatform solution. don't want to maintain (or write) both bash and powershell.

sogaiu16:12:01

...and i'd much prefer to write in something clojurish šŸ™‚

sogaiu16:12:12

i think babashka could really be a great way to learn clojure too

sogaiu16:12:22

or at least get started

nate_clojurians16:12:48

it's a little frustrating running into things that are missing, though

borkdude16:12:56

like with every new shiny tool probably

nate_clojurians16:12:38

oh the readme says java.nio.Files and not java.nio.file.Files

borkdude16:12:48

This tool is less than 6 months old.

nate_clojurians16:12:16

I don't mean to be critical btw

nate_clojurians16:12:19

I really like this

borkdude16:12:17

Thank you. Yes, it's not perfect yet, and the more exposure it gets, the better it gets hopefully

nate16:12:51

@borkdude including clj-http-lite is a great idea

nate_clojurians17:12:45

hmmm using resource instead of *file* w/ path munging is an interesting idea

borkdude17:12:28

@nate_clojurians Right, we could use the --classpath option you mean?

nate_clojurians17:12:51

yeah. except classpath has to automagically get the script's current directory or something

nate_clojurians17:12:00

especially when using it as a shebang

borkdude17:12:03

@nate_clojurians No, a classpath is just a collection of directories and jar files that will be searched for a matching file

nate_clojurians17:12:58

right, but what I mean is the actual problem is there are paths colocated with the script and something has to tell the script where to find them

borkdude17:12:16

I guess you can also just provide that as an argument to the script?

nate_clojurians17:12:19

and if it's in a shebang then the script itself can't call with --classpath

borkdude17:12:27

which makes the script also more flexible

nate_clojurians17:12:31

well it could, but the path is hardcoded

nate_clojurians17:12:07

I suppose, but in my case I don't need the flexibility, and it seems silly to me to have to tell the script where it is

borkdude17:12:21

@nate_clojurians There's a workaround for that:

$ cat script.clj
#!/bin/sh

#_(
   "exec" "bb" "$0" hello "[email protected]"
   )

(prn *command-line-args*)

./script.clj 1 2 3
("hello" "1" "2" "3")

borkdude17:12:03

(arguments in shebang that is)

nate_clojurians17:12:19

right, yeah, that would be better than hardcoding it

nate_clojurians17:12:48

still would be nice to have something built in

nate_clojurians17:12:19

something akin to ___dir___ in ruby

nate_clojurians17:12:25

or ___FILE___ in ruby

nate_clojurians17:12:08

I guess I'm more looking for clojure as a scripting language and this seems to fit with *file* in my brain

borkdude17:12:22

Right now you can also use: /tmp/foo.clj (chmod +x)

#!/bin/sh
#_(
   "exec" "bb" "$0" "$0" "hello" "[email protected]"
   )
(prn *command-line-args*)
In some other dir:
$ /tmp/foo.clj
Prints:
("/tmp/foo.clj" "hello")

nate_clojurians17:12:24

but compatability with clojure is a real concern

borkdude17:12:45

it's a bit hacky, but it works

borkdude17:12:46

In normal Clojure, you could probably read the metadata from a var and inspect the :file property. Have you tried if this works? If it does, we can just do that.

nate_clojurians17:12:05

No first class vars. Note that you can define and redefine global values with def / defn, but there is no var indirection.

nate_clojurians17:12:12

maybe that kept me from trying

nate_clojurians17:12:04

#!/usr/bin/env bb

(def foo "bar")

(prn (meta (var foo)))

nate_clojurians17:12:11

$ ./test.bb 
{:row 3, :col 6, :end-row 3, :end-col 9}

nate_clojurians18:12:46

would this be in sci?

laheadle18:12:09

clj-http-lite is going to obsolete my awesome curl wrapper! oh well šŸ™‚

borkdude18:12:02

@laheadle You can still use curl šŸ™‚

borkdude18:12:22

@nate_clojurians Where do you read this? Vars were recently introduced

borkdude18:12:19

Removed that, thanks

borkdude18:12:44

So would adding :file to that solve your problem?

nate_clojurians18:12:12

I think so? is that relative to cwd?

borkdude18:12:33

It would be good to see what clojure makes of it, when you execute clojure script.cljc

borkdude18:12:39

from various locations

laheadle18:12:11

like others, I find myself writing slightly larger scripts than the few-liners that glue together chunks of bash.

borkdude18:12:05

@nate_clojurians This seems to work for getting the scripting directory using clojure:

(def x)
(require '[ :as io])
(def script-dir (.getParentFile (io/file (:file (meta #'x)))))

nate_clojurians18:12:17

yeah, seems to get the absolute path too

borkdude18:12:35

Someone also mentioned https://github.com/schmee/java-http-clj which relies on JDK 11

borkdude18:12:42

might be good to explore before adding clj-http-lite

borkdude18:12:50

Hmm, it seems to rely on spec which is currently not well supported with GraalVM

borkdude19:12:04

But maybe inlining this small lib wouldn't be a problem

nate_clojurians19:12:47

@borkdude is that something I could work on, adding the :file? I might need a little direction to do it

nate_clojurians19:12:52

and probably wouldn't be until tomorrow

borkdude19:12:01

You could give it a try, but it requires some understanding of how files are processed either with passing a file argument, load-file and require. The way we handle classpath loading with a callback fn needs to change as well. I think it would be best if I gave it some more hammock time first

borkdude19:12:22

The logic is spread across babashka, the sci library and the edamame parser library

borkdude19:12:40

Each of these, or at least two, probably require changes

nate_clojurians19:12:33

here's where I am on this script. ~/Sync/dotfiles is where the script sits and subdirectories have the dotfiles:

borkdude19:12:21

Have you tried the suggested workaround?

borkdude19:12:58

Script looks neat btw

nate_clojurians19:12:56

I haven't yet, I'm pairing with someone on some things. I'll try to sneak it in later šŸ™‚

borkdude19:12:41

putting it in an env var could also work for now

nate_clojurians19:12:57

it's hard coded to ~/Sync/dotfiles but I'd like to make it independent of that path

borkdude20:12:38

@sogaiu I added a table to illustrate the combinations of input and output flags: https://github.com/borkdude/babashka/#input-and-output-flags

sogaiu20:12:47

oh, nice! šŸ‘

borkdude23:12:12

Small follow up to this morning's breaking change: https://github.com/borkdude/babashka/releases/tag/v0.0.45

borkdude23:12:25

I hope this only counts as one šŸ™‚