obb 2022-01-03

@zane has joined the channel

set the channel description: Ad-hoc ClojureScript scripting of Mac applications via Apple’s Open Scripting Architecture. https://github.com/babashka/obb

@borkdude has joined the channel

@james427 has joined the channel

@simongray has joined the channel

Do anyone happen to know where Apple documents their own “standard library”? I.e. what is the MDN for Apple’s JS.

The scripting guide you linked is great too.

You have access to Cocoa through JXA, so you can even create full-on applications if you want. But if you were to go down that path it might be worthwhile to just compile to JavaScript instead of running everything through obb.

I was thinking of creating an Input Method using Apple’s JS, so I might use this to get my feet wet

I also want to stress that this thing is in no way ready for prime time. There’ll be (lots of) bugs.

sure, it’s just fun, I get that 🙂

👍🏻 1

@zane I recommend putting these links in the README

@zane I also recommend watching the repo https://github.com/babashka/obb/watchers for issues :)

I created a couple of issues around the logistics of the project

@borkdude All these suggestions sound great. Will get to them as I’m able.

Cool, no hurry! :)

@zane Is this something specific to #obb or something that is relevant to SCI as well? https://github.com/babashka/obb/commit/ae9783c3ded24d7eca109a8cdbc608011ed62c10

@borkdude I wanted to discuss that with you, actually. Those changes might belong upstream.

This is handling a situation where you have a callable that for some reason isn’t an instance of Function &/or doesn’t have .apply.

I’m not sure how common that is outside of JXA.

@borkdude Yeah, I’m definitely going to add a lot more documentation. I wasn’t expecting eyes on the repository this quick. 😅

@soren has joined the channel

Another nice example for the README:

$ obb -e '(-> (js/Application "Google Chrome") (.-windows) (aget 0) (.activeTab) (.title))'
Slack | obb | clojurians

🙌 1
🙌🏻 1

Added to the README

@gnhuy91 has joined the channel

@mmz has joined the channel

@haiyuan.vinurs has joined the channel

Happy to just follow your lead on all the release engineering.

@volcano0909 has joined the channel

Next highest priority is probably a better printer.

$ obb -e '(range 10)'
I:null, start:0, end:10, step:1, $a:null, Ub:null, L:null, G:32375006, P:140800

@zane yes, the -e can just use prn

prn will blow up on object specifiers, no?

can make this conditional

👍🏻 1

Yep. There are a few other small design decisions to make, e.g. whether we want to default to osascript’s “human readable” output for object specifiers and the like. From man osascript: > osascript normally prints its results in human-readable form: strings do not have quotes around them, characters are not escaped, braces for lists and records are omitted, etc. This is generally more useful, but can introduce ambiguities. For example, the lists ‘{“foo”, “bar”}’ and ‘{{“foo”, {“bar”}}}’ would both be displayed as ‘foo, bar’. To see the results in an unambiguous form that could be recompiled into the same value, use the s modifier.

For nbb I've chosen to always use prn but we can fall back on console.log for object specifiers

we could also default to no printing for normal scripts

👍🏻 1

this is what nbb does

Sounds like a plan.

see how it's done with #nbb

You can now install #obb with:

brew install babashka/brew/obb

🎉 2

@kkharji has joined the channel

@rlhk.open has joined the channel

Great addition to then bb family. I guess https://github.com/Hammerspoon/hammerspoon could be replaced somehow?

Nice for the examples dir maybe?

obb -e '(-> (js/Application "Spotify") (.-currentTrack) (.name))'

Lots of fun to be had.

obb ❤️ bitbar / xbar / swiftbar

Put the result of any obb script in the menubar.

is there ways to explore these apps methods? 🤔

Open Script . File > Open Dictionary.

💯 1

Be sure to change the language dropdown to “JavaScript”.

Ah, we need to add this trick to the README

👍🏻 1

Maybe under FAQ

or Tips and Tricks

Is there a way to convert a spotify Track to a normal object?

e.g to convert into a clojure map

Trying to remember how to do that.

ObjC.unwrap(apps)? 🤔

saw it in the jxa doc

anyway this works:

$ obb -e '(defn track->clj [track] {:artist (.artist track) :album (.album track) :name (.name track)}) (-> (js/Application "Spotify") (.-currentTrack) track->clj str)'
{:artist "The Gathering", :album "How to Measure a Planet? (Deluxe Edition)", :name "Travel"}

@gnhuy91 I think that’s just for Objective-C objects.

(defn reminder->clj [reminder]
  {:name (.name reminder)
   :completed (.completed reminder)})

(-> (js/Application "Reminders")
    (.-defaultList)
    (.-reminders)
    (aget 0)
    (reminder->clj)
    (clj->js))
had fun with Reminders

👏🏻 1

I guess since SCI supports macros, you could write a macro to do (->clj obj .name .completed) or so

yea that'd be less verbose

Some returned objects will be records. For those there’s this: https://apps.apple.com/us/app/json-helper-for-applescript/id453114608

That’s what I was trying to remember earlier.

$ obb -e '(defmacro ->clj [obj & interops] (let [names (map #(clojure.string/replace (str %) #"[.-]" "") interops) ks (mapv keyword names) exprs (mapv #(list % obj) interops)] `(zipmap ~ks [~@exprs]))) 

(-> (js/Application "Spotify") (.-currentTrack) (->clj .artist .album .name) str)'
{:artist "The Gathering", :album "How to Measure a Planet? (Deluxe Edition)", :name "Travel"}

@clj149 has joined the channel

Found a useful macro that will help with interop:

$ obb -e '
(defmacro ->clj [obj & interops]
  (let [names (map #(clojure.string/replace (str %) #"[.-]" "") interops)
        ks (mapv keyword names)
        exprs (mapv #(list % obj) interops)]
    `(zipmap ~ks [~@exprs]))) 

(-> (js/Application "Spotify") (.-currentTrack) (->clj .artist .album .name) str)'

{:artist "The Gathering", :album "How to Measure a Planet? (Deluxe Edition)", :name "Travel"}

💯 4
🚀 1

@jesse.claven has joined the channel

@p4v4n has joined the channel

@sgepigon has joined the channel

@chromalchemy has joined the channel

@bmcgavin has joined the channel

@pithyless has joined the channel

@lee has joined the channel

It would be nice to be able to extend IPrintWithWriter to support object specifiers, but I think the protocol retrieval logic will also crash on them.

yeah, this is something that should be supported in SCI for other targets (nbb, babashka) as well.

or do you mean, extending it in the precompiled obb? (yes, this is what you meant)

what do you normally get with console.log on such a thing? also an error in JS?

If an expression evaluates to one you get back something akin to JS code that will produce it:

>> Application("Safari")
=> Application("Safari")

console.logging one will actually crash:

>> console.log(Application("Safari"))

!! Error: Error: Symbol.toPrimitive is not a valid class for application Safari

so what is it actually doing when it prints that? not console.log I assume? is there a special method they call on the object specifier to get this string? I'll be afk now, back tomorrow 💤

js/Automation.getDisplayString

Ah I see:

$ time obb -e '(-> (js/Application "Google Chrome") (.-windows) (aget 0) (.-tabs) (aget 0) js/Automation.getDisplayString pr-str)'
"Application(\"Google Chrome\").(0).(0)"

👍 1
👍🏻 1

and what happens if you extend the protocol to such a thing and then call this method on it?

Right. I had thought to just

(extend-protocol IPrintWithWriter
  ...
  (-pr-writer [obj writer _]
    (if (object-specifier? obj)
      ...
      ...)))
but we don’t get to that -pr-writer implementation. It crashes before that.

I’m trying to track down exactly what’s triggering the crash, but it’s hard. 😓

what is on the first three dots?

I’ve tried function, object, and default for the types.

is there not a type like js/ObjectSpecifier that you can extend the protocol to?

>> typeof Application("Safari")
=> "function"

we can also patch prn etc in the SCI context

string-print, probably.

probably. this stuff is in

but I was thinking {:namespaces {'clojure.core {'prn ...}}}

in the SCI opts

both are possible but the latter is less hacky.

but if console.log also crashes the thing, I'm not sure if we should try to fix it

don't improve on the JS behavior, just provide the same-but-CLJS behavior I'd say

when printing the return value with -e it's a different story, but there we can just write our own thing

We could provide a safe-print function in obb.core though, something to think about.

Need to think about whether that’ll work if an OS is in a collection.

Yeah, definitely.