babashka / nbb

Scripting in Clojure on Node.js using SCI
Eclipse Public License 1.0
847 stars 51 forks source link

Template String Support? #313

Closed jaidetree closed 1 year ago

jaidetree commented 1 year ago

Is your feature request related to a problem? Please describe. Trying to use https://github.com/google/zx with nbb again but its api has appeared to change since I've last worked with those two packages.

Describe the solution you'd like A clear and concise description of what you want to happen.

Thinking a similar js-template-str macro that partitions its list of args into strings and symbols. The list of strings is applied as the first arg to the tagged template fn and the symbols are passed in as args via apply.

(def some-var "./nbb.edn")

(js-template-str "git add " some-var)
;; # => I think
;; [#js ["git add"] "./nbb.edn"]

;; Could be used with zx$ like
(apply zx$ (js-template-str "cat" some-var))

Describe alternatives you've considered

Additional context

borkdude commented 1 year ago

I have read the post, but I don't understand some parts.

(js-template-str "git add " some-var)

Isn't js-template-str just the str function here?

What about using goog.string.format which is available in nbb?

jaidetree commented 1 year ago

goog.string.format works for problems where I'm just trying to format a string. But in the case of libraries like zx, goog string format would not work. Same with using the sql function from packages like slonik.

In js land:

import $ from 'zx'

$`ls -a ${path.join(process.cwd(), 'nbb.edn')}` 

Will call the $ function like:

$(['ls -a '], '/Users/j/projects/cljs-piano/nbb.edn')

Where each str is included in that first array of strings, then each interpolation value is provided as a function arg.

https://github.com/google/zx/blob/4999435182fe1f34f6b2ef2471184d9878456b5e/src/core.ts#L93

So that macro could be used like this:

(require '['zx' :refer [$]]
         '['path' :as path])

(apply $ (js-template-str "ls -a" (.join path (js/process.cwd) "nbb.edn")))

Took a stab at a first draft:

(defmacro js-template-str
  [& args]
  (let [[strs# args#] (partition-by string? args)
        result# (cons (clj->js (conj (vec strs#) "")) args#)]
    `(list ~@result#)))

(comment
  (macroexpand-1
    '(js-template-str "iconutil -c icns " (.join path (js/process.cwd) "nbb.edn"))))

;; => (#js ["iconutil -c icns "] (.join path (js/process.cwd) "nbb.edn"))
borkdude commented 1 year ago

I've had a discussion about template string support here:

https://github.com/squint-cljs/squint/discussions/40

There was also a string interpolation << macro in incubator:

https://clojure.github.io/clojure-contrib/strint-api.html

The output of your macro seems pretty specific to what zx expects or are there more general use cases?