Provide a way to detect the invoked script
Similar to (= *file (System/getProperty "babashka.file"))
Also see https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line
We can make a function in nbb.core to return the invoked file:
(nbb.core/script) ;;=> "foo.cljs"
(= *file* (nbb.core/script)) ;;=> true
Still have to come up with a good name.
Came up with the following hack to get the "top level" nbb file (as in python's top level module concept):
(require '["path" :as path])
(defn top-level-nbb-file []
(let [nbb-index (.indexOf js/process.argv "/usr/bin/nbb")] ;;get the index of nbb in the args array
(if (> nbb-index 0)
(get js/process.argv (inc nbb-index))))) ;; get the path of the script passed to nbb
(if-let [tl (top-level-nbb-file)]
(if (= *file* (path/resolve tl))
(-main)))
I'd also find this helpful. My workaround is (= nbb.core/*file* (:file (meta #'init))) but it's a bit annoying as #'init has to vary for each project
We can make a function in nbb.core to return the invoked file:
How about nbb providing a fn similar to (System/getProperties) and putting this data in there? Could make nbb and bb usage more similar (if that's a goal)
Yes, we can add a function for this to nbb.core.
Thanks @cldwalker - I used your hack in a project today.
@borkdude Is this still something that needs work?
@bolivier indeed
@borkdude I think most of the value here can be achieved relatively easily.
Looks like *file* is set when you invoke nbb like nbb some/script.cljs, but nil in the repl and with the main (-m app.core) invocation. I've got a fix for the -m case, which would make it possible to do this check with
(if *file*
:from-a-file
:repl)
Although it might be wise to set that value to "<repl"> and <"expr"> like babashka does.
Let me know what sounds good to you and I can open a PR.
The check we do in babashka is:
(if (= *file (System/getProperty "babashka.file")) (apply -main *command-line-args*))
Just checking *file* is not sufficient since you may be inside another namespace which is required from your invoked file.
Therefore I'd say we store the invoked file, as parsed from the command line options somewhere (I think it's already somewhere in a stored opts map) and we make a function in nbb.core: nbb.core/invoked-file that returns the invoked file.
To compare with *file* this file has to be absolutized (in the same way the nbb itself sets it for file) so it can be compared.
The (System/getProperty ...") equivalent of Node.js might be storing values on js/process. E.g. js/process.version returns the Node.js version. js/process.env contains environment variables.
We could store information on js/process.nbb, e.g. js/process.nbb.file. But maybe a function in core would be the most idiomatic.
@bolivier implemented (nbb.core/invoked-file) which was just published:
foo.cljs
(prn (nbb.core/invoked-file))
(prn (= nbb.core/*file* (nbb.core/invoked-file)))
npx nbb@latest foo.cljs
"/Users/borkdude/dev/nbb/foo.cljs"
true
Thank you @bolivier !