Fork me on GitHub
#babashka
<
2023-06-25
>
joakimen14:06:21

I found a few scattered conversations, but couldn't find a conclusion. Does babashka support a global bb.edn? Tried putting one in /.config/babashka, /.config/.babashka and ~/.babashka without luck Mainly looking to reuse generic tasks 🙂

borkdude14:06:43

It doesn't support global tasks but you can accomplish this by putting a bb.edn anywhere and then make a wrapper script that does: wrapper

#!/usr/bin/env bash
bb --config ~/.my-config/bb.edn "$@"
and then you can call wrapper my-task

joakimen14:06:19

I see, how will this cooperate with local bb.edn files? E.g. being in a project, and having access to global and local tasks

joakimen14:06:41

Ok, gave it a shot and it seems like it doesn't support overlaying multiple configs (that is, I can't make it read project-local and referenced config at the same time). I can imagine it's a bit tricky to implement

borkdude14:06:27

bb.edn files are never merged

borkdude14:06:36

for global things, it's probably better to make a project with a bunch of scripts. hello:

#!/usr/bin/env bb

(println "hello") 
and then add that directory to your path

borkdude14:06:55

Then you can invoke hello from anywhere on your system. It even works when hello uses something from the local bb.edn

joakimen14:06:14

Right, because when bb is invoked from the shebang, it picks up the bb.edn in the current project, so that context is available in the global script sort of

joakimen14:06:25

Thats good!

joakimen12:07:56

A followup question to this; is there a way to explicitly deny a script installed using bbin from respecting bb.edn-files in the current dir?

joakimen13:07:39

I don't think so, in my case everything is working as intended (when a bb-script is invoked, the bb.edn in the current dir is respected). It's just that I have several global, general purpose scripts that should just run as-is and not try to parse bb.edn files if present

joakimen13:07:32

I didn't really notice this until I started pulling down several bb projects from other people, and noticed how running one of my general purpose scripts in their repo results in installing their dependencies, while I just wanted the script to run as it was installed. I figured this might be related to bbin and how scripts are installed

borkdude13:07:27

is something not working though, or is it just that you don't want to parse the current bb.edn?

joakimen13:07:44

The latter, yeah 🙂 Sometimes I do (like in this thread, for global tasks and such), and sometimes I don't (my personal system utilities and such)

borkdude14:07:15

does it really matter though? when the deps are already downloaded, after that it's a no-op?

joakimen14:07:46

Maybe not, but won't the bb.edn from <insert random project i cloned from github> technically be able to modify my bb-script invocation by specifying a different namespace for main, or things like that? Just thinking out loud here

borkdude14:07:55

can you do cat $(which <global-bb-util>) and paste the first few lines?

joakimen14:07:03

#!/usr/bin/env bb

; :bbin/start
;
; {:coords {:bbin/url "file:///Users/joakim/bin/bbfile"}}
;
; :bbin/end
Installed using bbin install . in /Users/joakim/bin/bbfile, and the bbin-directive in bb.edn is :bbin/bin {bbfile {:ns-default bbfile.cli}}

borkdude14:07:38

can you give more output?

borkdude14:07:06

I don't think the local bb.edn will mess with the bbin script

borkdude14:07:20

the bbin script just starts another instance of bb

borkdude14:07:43

with an explicit --config

joakimen14:07:12

Ok, I don't quite understand what's going on here yet, but I'll take your word

borkdude14:07:57

the script that bbin installs is just a script that boots another instance of bb

joakimen14:07:17

Yeah that part is ok, more so how the config is determined. Anyway, now I got to one of the problems that I came across earlier today; 1. i run a bb-sdript in a directory that has a bb.edn (which is picked up) 2. that bb.edn contains a local, relative reference to another project in the file system that i don't have a. e.g. :deps {io.github.kevin/app {:local/root "../mylib"}} 3. bb-script crashes This was just an example scenario where I'd cloned someones project, and I didn't have their directory structure. Considering several clojure devs use this local/root-thing for convenience, I figure this problem might pop up again

borkdude14:07:22

Yeah, this is not specific to bb. Any deps.edn with a local/root to a non-existing project will also make clj crash for example

joakimen14:07:58

Yeah I guess! It does make (my) scripts more fragile though, so if there is a way to prevent reading bb.edn-files from a bb-script installed using bbin, I would love to hear it. Might be a conversation for #C0400TZENE7 though

borkdude14:07:18

neh, it's not in bbin. the order of the configuration is determined here: https://github.com/babashka/babashka/blob/657adff33612c198e2ee02085d31a0707d4d802c/src/babashka/main.clj#L1131 first we check if there is a bb.edn in the local dir. if so, then that is the config

borkdude14:07:12

no sorry, wrong

joakimen14:07:16

Yeah, but considering bbin overrides it, like when assembling base-commandin the above script

borkdude14:07:01

what you're seeing isn't caused by the bbin script but by babashka not finding a relative bb.edn to the bbin boot script, so it still reads the local one

borkdude14:07:06

the order is (correction to what I said before): • explicit --config argument • a relative bb.edn to the invoked script (bbin could add a dummy bb.edn to the relative file for example) • bb.edn in the local directory

borkdude14:07:37

if you add a bb.edn file relative to your global tool with an empty map, this should be a workaround to your problem

joakimen14:07:24

Ok, but in this case the invoked script does have a relative bb.edn

❯ ls -l
drwxr-xr-x joakim  96 B Sun Jul  2 19:38:13 2023  .calva
drwxr-xr-x joakim 224 B Mon Jul  3 16:06:20 2023  .clj-kondo
drwxr-xr-x joakim 256 B Mon Jul  3 16:06:20 2023  .cpcache
drwxr-xr-x joakim  96 B Mon Jul  3 16:06:29 2023  .lsp
drwxr-xr-x joakim  96 B Sun Jul  2 13:01:33 2023  src
.rw-r--r-- joakim 152 B Sun Jul  2 13:01:33 2023  bb.edn
.rw-r--r-- joakim  91 B Sun Jul  2 13:01:33 2023  deps.edn
.rw-r--r-- joakim   9 B Sun Jul  2 13:01:33 2023  README.md

borkdude14:07:56

where is bbfile?

borkdude14:07:07

that's the script I meant

joakimen14:07:19

:bbin/bin {bbfile {:ns-default bbfile.cli}}
uses the tools syntax

borkdude14:07:52

I mean, I don't see bbfile in your ls output. The bb.edn should be relative to that one - in that case bb will not read the dir local one

joakimen14:07:27

oh. so how does that work when you install scripts/projects like this, with one bb.edn?

borkdude14:07:53

just add an empty map bb.edn file in. your bbin bin dir

borkdude14:07:25

echo '{}' > ~/.babashka/bbin/bin/bb.edn

borkdude14:07:31

this should solve your problem

joakimen14:07:08

Yeah that works! Not to nitpick now, but this will prevent the global tasks-scripts we discussed earlier from picking up local bb.edn files then, or?

borkdude14:07:43

no, it won't :)

borkdude14:07:57

eh yes, it will

borkdude14:07:04

it will solve the problem you reported earlier

joakimen14:07:58

Alright, I'll give it some thought. Thanks a lot for taking the time! By the way, saw your talk on babashka conf! Very interesting to hear about your experiences with the community and ecosystem, can easily have a longer talk next time 😁

👍 2
Oliver Marshall15:06:53

Hi! I’m writing a script with some long log outputs that I want to scroll in a fixed section of the terminal. I’ve got that working using ANSI control codes (lots of useful info https://github.com/dylanaraps/writing-a-tui-in-bash). The one problem I’m having is knowing the current cursor position so I can set it up from the current line down. There’s the control code \033[6n which returns this to stdin (I think) but I’m having trouble reading it. Here’s what I’ve tried so far, any other ideas?

(ns test
  (:require [babashka.process :as p :refer [shell]]
            [ :as io]
            [clojure.string :as str]))

(println "Test 1")
;; Try using `shell` & printf
(-> (shell {:out :string} "printf '\033[6n'")
    :out
    (str/split #";")
    println)

(println "Test 2")
;; Try printing and reading the ANSI code ourselves
(with-open [reader (io/reader *in*)]
  (println "\033[6n")
  (let [c (.read reader)]
    (println "Read character:" (str c))))

Oliver Marshall18:06:16

Ok, so I’ve managed to figure the start of something out. Looks like running stty -icanon before other commands allows the process to read from stdin without blocking waiting for the user to press enter. Not sure how portable it is but its POSIX which works for me 🙂 (source: https://stackoverflow.com/a/72991794 🙏)

Oliver Marshall19:06:05

For anyone looking, here’s what worked for me:

(ns test
  (:require [babashka.process :refer [shell]]
            [ :as io]))

(defn read-upto-char
  "Reads from stdin until the given character is found.
  Returns the string read, including the character."
  [upto]
  (let [r (io/reader *in*)]
    (loop [out ""]
      (let [c (char (.read r))]
        (if-not (= c upto)
          (recur (str out c))
          (str out c))))))

(defn parse-cursor-position
  "Parse the cursor position from the given ANSI code."
  [cursor-position]
  (let [[_ row col] (re-matches #"^\033\[(\d+);(\d+)R$" cursor-position)]
    {:row (Integer/parseInt row)
     :col (Integer/parseInt col)}))

;; Disable canonical mode
;; This is required for reading ANSI codes without blocking for a newline
(shell "stty -icanon")

;; Disable echo
;; This is required so that the user doesn't see the output ANSI codes
(shell "stty -echo")

;; Get the cursor position
;; 
(println "\033[6n")

(->> (read-upto-char \R)
    parse-cursor-position
    println)

borkdude07:06:01

ah nice that you figured it out