I have some clj files that implement some common/shared tasks that I use in many of my bb.edn files. Usually I just copy/paste the scripts/ dir and bb.edn around, but I'd like to be able to manage those task scripts in one place. What's the best way to go about doing that?
Here is a minimal sort of bb.edn to give you an example:
{:paths ["scripts"]
:deps {io.github.paintparty/bling {:mvn/version "0.4.2"}}
:tasks {
build-assets {:task (exec 'assets/.-main)}
datomic {:task (exec 'datomic/-main)}}}
the scripts dir has assets.clj and datomic.clj, and they dep on the bling libSure, you can put your code in a library and just use the library. You still have to hook up the library to the task names though
So in addition to bling you would have another library
{:deps {io.github.paintparty/bling {:mvn/version "0.4.2"}
myns/shared-scripts {:mvn/version "0.0.0"}}
:tasks {
build-assets {:task ??}
datomic {:task ??}}}
yeah, you don't have to put it on mvn though. it can be a local/root or git/url+git/sha lib
can the :task value can just be normal clojure code like
:build-assets {:task shared-scripts.assets/-main} ?
yes
ah nifty! I assumed it was something special I guess. Is there a way to provide the :task and :doc from the library?
no, unfortunately not, although doc will be derived from the var I think, if you just use the symbol
:build-assets shared-scripts.assets/task-def ? which is something like (def task-def {:task ... :doc ...})
the task names are always static
gotcha, ok, that is probably good enough, the key is that something useful shows up in bb tasks
This works quite well!
One thing I might like to do is use data defed in the bb.edn file:
{:deps {mylib/tasks {:local/root "../../some/path/tasks"}}
:tasks {:init (do
(def css-build-opts {:input "resources/public/main.css"
:output "resources/public/compiled.css"}))
asset-build mylib.tasks/css-main ;; <-- this function gets cli args but cannot access css-build-opts
asset-build2 {:task (mylib.tasks/css-main css-bild-opts *command-line-args*)
:doc "Have to manually copy the docstring"}}}now you only have to copy your bb.edn instead of also your code
fair enough
Do you have any plans to support dynamic tasks or loading tasks from deps?
I consider it a feature that all tasks are statically known for people glancing the bb.edn (similar to aliases in deps.edn )
I've just started on the path of using babashka instead of Bash scripts. (That was hard. I've spent about 5 years with Bash as my primary language in my last job so I'm pretty comfortable with it, and somewhat skeptical of replacing it. But I want to give it a go.) I'm stuck at what I'm guessing is a very-easy-to-fix PEBKAC: how do I construct new paths?
I have:
#!/usr/bin/env bb
(ns t
(:require [babashka.process :as p]
[babashka.fs :as fs]))
(def dir (fs/parent (fs/parent *file*)))
(defn compress
[]
(let [data-dir (
What do I type now to get the equivalent path of "$DIR"/_data?user=> (apropos "path")
(babashka.classpath/add-classpath babashka.classpath/get-classpath babashka.classpath/split-classpath babashka.fs/exec-paths babashka.fs/path babashka.fs/path-separator babashka.fs/real-path babashka.fs/split-paths babashka.wait/wait-for-path clojure.core/*compile-path* clojure.core/*source-path* clojure.zip/path selmer.parser/known-variable-paths selmer.parser/set-resource-path!)
user=> (doc babashka.fs/path)
-------------------------
babashka.fs/path
([f] [parent child] [parent child & more])
Coerces f into a Path. Multiple-arg versions treat the first argument as
parent and subsequent args as children relative to the parent.
nil
user=> (babashka.fs/path "/tmp" "trace.snowflake")
#object[sun.nio.fs.UnixPath 0x4335fbfd "/tmp/trace.snowflake"]
user=> ask the runtime for things related to paths, get a docstring of one that looks promising, check it in the repl
(let [data-dir (fs/file dir "_data")]
...)Oh. Thanks!
(i truly think apropos and doc are phenomenal tools that are default in the runtime)
I was looking at https://github.com/babashka/fs/blob/master/API.md#babashka.fs/path and the description at the top ("Coerces f into a Path.") did not hint at that at all.
oh you mean multiple args to fs/path?
Yes, I completely missed that.
does that too. Probably I didn't mention it because I was so used to it. Let's fix that right away. Thanks for trying bb :)
I never knew that about either ๐ฎ
Do you want a PR or is it easier for you to fix directly?
yeah. much better than string wrangling with "/" , more portable between OSes too
Oh PR would be sweet!
Are the docs generated somehow or is editing the md file directly the right approach?
docs are generated from the var docstrings using bb quickdoc
๐
so the docs are in the docstrings in the code
and then extracted and frobnicated into a .md file
tl;dr: just update the docstring in the code, that will do, don't worry about anything else
Yep, following that. So the information I was missing is in the docstring, but not in the first sentence, which is why it wasn't at the top.
oh...
Because quickdoc https://github.com/borkdude/quickdoc/blob/main/src/quickdoc/impl.clj#L37 for the summary at the top.
a little too quick
I've updated my PR.
Much better than it was. I think we can now delete the second sentence, do you agree?
I think I would be fine without it, but it does add more precision, so really up to you.
Happy to remove it in my PR if you think that's the right call.
I'll merge it, you've been through enough as a fresh bb scripter :)
โ
Thanks!
Is there an equivalent to Python's if __name__ == "__main__"? I'm feeling a desire for a REPL-connected workflow, and that requires not running my currently-top-level "main" action on file load. The file in question is meant to replace a Bash script, so ideally it's called directly with a shebang (that currently works, but with top-level side-effect) and does not have a name ending in .clj. Open to the notion I'm holding it wrong.
Yes search the babashka book for Python, afk now :)
Got it, thanks! I'd searched for "shebang", didn't think of searching for Python ๐
http://book.babashka.org itโs somewhere in there
Yes, I have found it:
(= *file* (System/getProperty "babashka.file"))babashka.fs/match has four options, with no documented default value. The code does give them (implicit) default values. Would a PR adding the default values to the docstring be accepted, or is the omission deliberate? (i.e. they are implementation details)