nbb icon indicating copy to clipboard operation
nbb copied to clipboard

Provide a way to detect the invoked script

Open borkdude opened this issue 4 years ago • 5 comments

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.

borkdude avatar Oct 30 '21 18:10 borkdude

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)))

gtoast avatar Nov 15 '21 01:11 gtoast

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

cldwalker avatar Dec 14 '21 19:12 cldwalker

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)

cldwalker avatar Dec 14 '21 20:12 cldwalker

Yes, we can add a function for this to nbb.core.

borkdude avatar Dec 14 '21 20:12 borkdude

Thanks @cldwalker - I used your hack in a project today.

chr15m avatar Apr 12 '22 05:04 chr15m

@borkdude Is this still something that needs work?

bolivier avatar Mar 29 '23 16:03 bolivier

@bolivier indeed

borkdude avatar Mar 29 '23 16:03 borkdude

@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.

bolivier avatar Mar 29 '23 19:03 bolivier

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.

borkdude avatar Mar 29 '23 20:03 borkdude

@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 !

borkdude avatar Mar 31 '23 19:03 borkdude